rapid7/metasploit-framework — pull request #2119 by jvennix-r7 (2013-07-18 16:31:36+00:00)
Title: RM #2095: x86 osx exec payload doesnt accept args

### Description:

Updates the osx x86 exec payload in the following ways:
- adds support for passing an arg array to execve()
- removed an unnecessary copy-to-stack (the data was already stuffed in instruction memory)

### Verification:
- [ ] Checkout the master branch and generate an osx/x86/exec payload that runs the `/bin/ls` command:

$ git checkout master
$ ./msfpayload osx/x86/exec CMD="/bin/ls" R > ~/Desktop/exec_master.bin

- [ ] Checkout my branch and generate the same payload:

$ git checkout jvennix-r7:bug/x86-osx-exec-payload-doesnt-accept-args
$ ./msfpayload osx/x86/exec CMD="/bin/ls" R > ~/Desktop/exec_joev.bin

- [ ] Do a diff of the two payloads. It will look like:

![payload_diff](https://f.cloud.github.com/assets/1184013/820060/2e36cf62-efbd-11e2-84e5-c43189c95db6.png)

Here is a disassembled comparison, for reference:

![asm-compare](https://f.cloud.github.com/assets/1184013/820365/eeea3d3e-efc2-11e2-8038-2a0a0cdd4675.png)

Here are the reasons for the changes:
1. Delete 1 byte at offset 0x2: This pushed `eax` (0x00) on to the stack, which was ended up "in front" of the string that gets copied to the stack. It served no other purpose so I killed it.
2. Delete 6 bytes at offset 0xf. This removes the copy-string-to-stack call (the `repne movsb` instruction) and the set up required for this instruction. The data is already in instruction memory, so we can just use the original reference.
3. Replace 7 bytes at offset 0x16 with 1 byte (same as #2).

- [ ] Now test the payload. Output as an executable:

$ ./msfpayload osx/x86/exec CMD="/bin/ls" X > ~/Desktop/exec_joev_exe.bin
$ chmod +x ~/Desktop/exec_joev_exe.bin
$ arch -i386 ~/Desktop/exec_joev_exe.bin

- [ ] You should see an output like `usage: ls [-ABCFGHLOPRSTUWabcdefghiklmnopqrstuwx1] [file ...]`

- [ ] Now test passing arguments. Compile the following C program:

#include
int main(int argc, char *argv[]) {
int x;
for (x = 0; x < argc; x++) {
printf("%s\n", argv[x]);
}
return 0;
}

$ gcc ~/Desktop/print_args.c -O ~/Desktop/print_args
$ ~/Desktop/print_args # should output "./print_args" to the console

- [ ] Compile a payload that passes args:

$ ./msfpayload osx/x86/exec CMD="/Users/joe/Desktop/print_args a bb ccc dddd eeeee ffffff ggggggg hhhhhhhh" X > ~/Desktop/exec_joev_exe_args.bin
$ chmod +x ~/Desktop/exec_joev_exe_args.bin
$ arch -i386 ~/Desktop/exec_joev_exe_args.bin

- [ ] You should see the following output:

/Users/joe/Desktop/print_args
a
bb
ccc
dddd
eeeee
ffffff
ggggggg
hhhhhhhh