Hacker News new | ask | show | jobs
by joev_ 4462 days ago
Good writeup, not enough people go in depth like this on shellcode!

Metasploit has some decent shellcode. What you wrote here is essentially a specialized execve payload. Some of metasploit's execve payloads support passing arguments to execve, by building the args array on the fly:

https://github.com/rapid7/metasploit-framework/blob/master/m...

There are also lots of reverse shells like this, and reverse stagers too. Additionally, there are other solutions to bind shells being noisy:

See https://github.com/rapid7/metasploit-framework/pull/3017

Which causes the port to show as "closed" in a scan, and

https://github.com/rapid7/metasploit-framework/pull/2981

Which prevents other IPs from jacking your shells.

EDIT: also I think you need a null byte at the end of everything, otherwise the last arg string might not terminate correctly depending on what's in memory.

1 comments

>also I think you need a null byte at the end of everything, otherwise the last arg string might not terminate correctly depending on what's in memory.

That is what mov long [esi+64],eax does at line 19, it puts a NULL on top of FFFF to properly terminate the array of parameters. It is also reused as last argument of execve() at line 23.

I know I have tested this shellcode against a vulnerable machine (as a CTF, nothing illegal) and it worked well enough.

Ah cool I see that now, thanks :) It would have been the kind of bug that only bothers you once in a while, that's why I pointed it out.
"I know I have tested this shellcode against a vulnerable machine..."

In your article you say arguments to syscalls via interrupt 0x80 are passed in registers. That sounds like Linux and Microsoft.

Have you tested this against a vulnerable machine that passes arguments on the stack?

I think I read somewhere that this is how UNIX handles arguments.

Maybe I should've dug a bit deeper in the details with the syscalls stuff, but I didn't want to make it become a tedious read.

System calls on Linux (I'm no windows or BSD/OSX expert so I can't talk about those systems) used to be handled with int 0x80 instructions and even today this has become a common myth/misconception. Since Pentium 4 the architecture has changed in favor of better performance with the linux-gate/linux-vdso virtual system call bridge[0]and modern system calls in actual applications/libc use sysenter/sysexit. There's still compatibility for "legacy" int 0x80 though so this is not a problem.

This said, int 0x80 expects system calls arguments to be passed on the registers on Linux, again I don't know about Windows and BSD/OSX. Keep in mind that this article is very "naive" in writing and expectations, most of these buffer overflow exploits don't even work anymore in most servers, most distributions provide memory protection, ASLR, stack guards, canaries, read-only GOT, etc etc. There are still interesting ways to skip these security measures[1][2] but this is unrelated.

Bottom line is, take this article with a grain of salt, it's purely educational/informative, not aimed towards actually exploiting modern vulnerable systems :)

[0] http://www.trilithium.com/johan/2005/08/linux-gate/

[1] https://en.wikipedia.org/wiki/Return-oriented_programming

[2] http://www.cs.vu.nl/~herbertb/papers/srop_sp14.pdf

Most BSDs kernels have an emulator mode when they accept int 0x80 syscalls. Some parameters are different than Linux though.