您的位置:首页 > 其它

简略分析某外挂外壳

2005-04-13 22:59 155 查看
[align=center]简略分析某外挂外壳[/align]【目 标】:英雄王座 v0.001.014
【工 具】:Olydbg1.1(diy版)、LORDPE、ImportREC1.6F
【任 务】:脱马甲
【操作平台】:Windows Xp sp2
【作 者】:loveboom[DFCG][FCG][US]
【简要说明】:这里一个比较奇怪的外壳,在外面看不到关于这个壳的任何说明,壳通过一个DLL对原程序进行解压,解压完毕执行原程序,是一个比较有新意的加壳方式。
【详细过程】:OD没什么特别的设置,打开所有异常项就行了。先直接用Lordpe 看看这个壳的一点信息:
比较有意思,程序只用一个DLL来解压并运行程序,因为壳是通过DLL解压后,再运行,所以我们不能直接让OD停在OEP处,因为OD一般是在程序的oep处下个cc断,这样才会中断在程序入口处。改一下OD的设置:让OD中断在系统DLL中。这样就可以加载程序了,因为壳后面会改IAT到壳里,所以我们先要在程序里新增一个段。我的做法是用winhex新键一个大小为35KB(这个因IAT大小而定)的空白文件,然后用LORDPE载入程序文件并新增一个段,选择从磁盘载入段就行了。最下面那个段就是我新加的.现在再次用OD载入目标程序,现在中断在系统中:7C921231 C3 RETN ; 中断在系统dll中7C921232 8BFF MOV EDI,EDI断下后在程序的CODE段下F2断点:然后按F9运行程序,运行后,程序中断在ShellDll.dll中,也就是DLL解码程序文件处:100025A2 8BCE MOV ECX,ESI ; 如果没有解压完跳到这里继续100025A4 6A 01 PUSH 1100025A6 8B11 MOV EDX,DWORD PTR DS:[ECX] ; 中断在这里100025A8 895424 18 MOV DWORD PTR SS:[ESP+18],EDX ; 这里的代码对原程序进行解码.100025AC 8B41 04 MOV EAX,DWORD PTR DS:[ECX+4]100025AF 894424 1C MOV DWORD PTR SS:[ESP+1C],EAX100025B3 8B51 08 MOV EDX,DWORD PTR DS:[ECX+8]100025B6 895424 20 MOV DWORD PTR SS:[ESP+20],EDX100025BA 8D5424 18 LEA EDX,DWORD PTR SS:[ESP+18]100025BE 8B41 0C MOV EAX,DWORD PTR DS:[ECX+C]100025C1 8D4C24 28 LEA ECX,DWORD PTR SS:[ESP+28]100025C5 51 PUSH ECX100025C6 55 PUSH EBP100025C7 52 PUSH EDX100025C8 8D4C24 20 LEA ECX,DWORD PTR SS:[ESP+20]100025CC 894424 30 MOV DWORD PTR SS:[ESP+30],EAX100025D0 E8 5BEBFFFF CALL 10001130100025D5 8B4C24 24 MOV ECX,DWORD PTR SS:[ESP+24]100025D9 8B5424 28 MOV EDX,DWORD PTR SS:[ESP+28]100025DD 8BC6 MOV EAX,ESI100025DF 83C6 10 ADD ESI,10100025E2 4B DEC EBX100025E3 8908 MOV DWORD PTR DS:[EAX],ECX100025E5 8B4C24 2C MOV ECX,DWORD PTR SS:[ESP+2C]100025E9 8950 04 MOV DWORD PTR DS:[EAX+4],EDX100025EC 8B5424 30 MOV EDX,DWORD PTR SS:[ESP+30]100025F0 8948 08 MOV DWORD PTR DS:[EAX+8],ECX100025F3 8950 0C MOV DWORD PTR DS:[EAX+C],EDX100025F6 ^ 75 AA JNZ SHORT 100025A2 ; 没解压完跳回去100025F8 5D POP EBP100025F9 5B POP EBX100025FA 8D4C24 08 LEA ECX,DWORD PTR SS:[ESP+8]100025FE C74424 34 FFFFF>MOV DWORD PTR SS:[ESP+34],-110002606 C1E7 04 SHL EDI,410002609 E8 22EAFFFF CALL 100010301000260E 8B4C24 2C MOV ECX,DWORD PTR SS:[ESP+2C]10002612 8BC7 MOV EAX,EDI10002614 5F POP EDI10002615 5E POP ESI10002616 64:890D 0000000>MOV DWORD PTR FS:[0],ECX1000261D 83C4 30 ADD ESP,3010002620 C2 1000 RETN 10 ; 我们可以直接在这里按F4,执行到这里断下后,直接F4执行到10002620处,注意因为OD在程序OEP处下了cc,这里解码后的OEP部分代码错误,所以我们要在这时改一个OEP代码,然后再改回去就行了。操作完毕后再一次CODE段断点,这样就到了IAT处理块,我们来分析一下IAT的处理:1000236B 8B4424 0C MOV EAX,DWORD PTR SS:[ESP+C]1000236F C606 E9 MOV BYTE PTR DS:[ESI],0E9 ; 再一次下段后中断在这里,这里填入远程跳,让IAT的部分去壳里10002372 2BC6 SUB EAX,ESI ; 计算跳转的距离10002374 83C0 FB ADD EAX,-510002377 8946 01 MOV DWORD PTR DS:[ESI+1],EAX ; 填入跳去远程地址1000237A 8B5424 14 MOV EDX,DWORD PTR SS:[ESP+14] ; 取要保存输入表的地址1000237E 8B4424 20 MOV EAX,DWORD PTR SS:[ESP+20] ; 取出跳去IAT的代码,用于然后比较,跳去API一般是 ff25,ff15之类的等10002382 3D 2D8B0000 CMP EAX,8B2D ; 比较是不是mov ebp,ds:[xxxxxxxx]的样式10002387 893A MOV DWORD PTR DS:[EDX],EDI ; 把IAT填入壳里面10002389 0F8F 9C000000 JG 1000242B ; 如果大于8b2d就跳1000238F 0F84 86000000 JE 1000241B ; 如果等于就跳去8b2d情况的处理10002395 3D 158B0000 CMP EAX,8B15 ; 这里比较是不是 MOV EDX, DS:[XXXXXXXX]的样式1000239A 7F 68 JG SHORT 10002404 ; 如果大于就跳1000239C 74 38 JE SHORT 100023D6 ; 等于就跳去处理8b15的情况1000239E 3D A1000000 CMP EAX,0A1 ; 比较是不是 MOV EAX,DS:[xxxxxxxx]的情况100023A3 74 1B JE SHORT 100023C0 ; 如果是则跳去处理100023A5 3D 0D8B0000 CMP EAX,8B0D ; 判断是否为MOV ECX,DS:[xxxxxxxx]100023AA 0F85 D9000000 JNZ 10002489 ; 如果不是则跳100023B0 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10] ; 处理MOV ECX,DS:[xxxxxxxx]的情况100023B4 8D46 06 LEA EAX,DWORD PTR DS:[ESI+6]100023B7 C601 8B MOV BYTE PTR DS:[ECX],8B100023BA C641 01 0D MOV BYTE PTR DS:[ECX+1],0D100023BE EB 24 JMP SHORT 100023E4100023C0 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10] ; 处理MOV EAX,DS:[xxxxxxxx]的情况100023C4 8D46 05 LEA EAX,DWORD PTR DS:[ESI+5]100023C7 C601 A1 MOV BYTE PTR DS:[ECX],0A1100023CA 8B5424 14 MOV EDX,DWORD PTR SS:[ESP+14]100023CE 8951 01 MOV DWORD PTR DS:[ECX+1],EDX100023D1 83C1 05 ADD ECX,5 ; 因为MOV EAX,DS:[xxxxxxxx]机器码只有五位,所以处理有一点不同100023D4 EB 18 JMP SHORT 100023EE100023D6 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10] ; 处理MOV EDX, DS:[XXXXXXXX]的情况100023DA 8D46 06 LEA EAX,DWORD PTR DS:[ESI+6]100023DD C601 8B MOV BYTE PTR DS:[ECX],8B100023E0 C641 01 15 MOV BYTE PTR DS:[ECX+1],15100023E4 8B5424 14 MOV EDX,DWORD PTR SS:[ESP+14] ; 处理完那个跳之里类的,就写出DS:[xxxxxxxx]中的地址,地址就是eip的前一句的地址100023E8 8951 02 MOV DWORD PTR DS:[ECX+2],EDX100023EB 83C1 06 ADD ECX,6100023EE 2BC1 SUB EAX,ECX ; 计算距离100023F0 C601 E9 MOV BYTE PTR DS:[ECX],0E9 ; 在壳里增加完跳去API的代码后,填入要jmp返回程序的代码100023F3 83E8 05 SUB EAX,5100023F6 5F POP EDI100023F7 8941 01 MOV DWORD PTR DS:[ECX+1],EAX ; 填入返回地址100023FA 5E POP ESI100023FB 33C0 XOR EAX,EAX100023FD 5B POP EBX100023FE 83C4 10 ADD ESP,1010002401 C2 0C00 RETN 0C10002404 3D 1D8B0000 CMP EAX,8B1D ; 判断是否为MOV EBX,DS:[xxxxxxxx]10002409 75 7E JNZ SHORT 10002489 ; 如果不是则跳1000240B 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10] ; 处理MOV EBX,DS:[xxxxxxxx]的情况1000240F 8D46 06 LEA EAX,DWORD PTR DS:[ESI+6]10002412 C601 8B MOV BYTE PTR DS:[ECX],8B10002415 C641 01 1D MOV BYTE PTR DS:[ECX+1],1D10002419 ^ EB C9 JMP SHORT 100023E41000241B 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10] ; 处理mov ebp,ds:[xxxxxxxx]的情况1000241F 8D46 06 LEA EAX,DWORD PTR DS:[ESI+6]10002422 C601 8B MOV BYTE PTR DS:[ECX],8B10002425 C641 01 2D MOV BYTE PTR DS:[ECX+1],2D10002429 ^ EB B9 JMP SHORT 100023E41000242B 3D 15FF0000 CMP EAX,0FF15 ; 判断是否为CALL DS:[xxxxxxxx]10002430 7F 3D JG SHORT 1000246F ; 如果大于则跳10002432 74 2C JE SHORT 10002460 ; 等于就跳去处理CALL DS:[xxxxxxxx]10002434 2D 358B0000 SUB EAX,8B35 ; 这里处理否为MOV ESI,DS:[xxxxxxxx]10002439 74 15 JE SHORT 10002450 ; 相等则跳1000243B 83E8 08 SUB EAX,8 ; 这里用另一种方式判断是否为MOV EDI,DS:[xxxxxxxx]1000243E 75 49 JNZ SHORT 10002489 ; 如果不是则跳10002440 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10] ; 处理MOV EDI,DS:[xxxxxxxx]的情况10002444 8D46 06 LEA EAX,DWORD PTR DS:[ESI+6]10002447 C601 8B MOV BYTE PTR DS:[ECX],8B1000244A C641 01 3D MOV BYTE PTR DS:[ECX+1],3D1000244E ^ EB 94 JMP SHORT 100023E410002450 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10] ; 处理MOV ESI,DS:[xxxxxxxx]的情况10002454 8D46 06 LEA EAX,DWORD PTR DS:[ESI+6]10002457 C601 8B MOV BYTE PTR DS:[ECX],8B1000245A C641 01 35 MOV BYTE PTR DS:[ECX+1],351000245E ^ EB 84 JMP SHORT 100023E410002460 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10] ; 处理CALL DS:[xxxxxxxx]的情况10002464 8D46 06 LEA EAX,DWORD PTR DS:[ESI+6]10002467 C601 FF MOV BYTE PTR DS:[ECX],0FF1000246A ^ E9 71FFFFFF JMP 100023E01000246F 3D 25FF0000 CMP EAX,0FF25 ; 判断是否为JMP DS:[xxxxxxxx]10002474 75 13 JNZ SHORT 10002489 ; 如果不是则跳10002476 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10] ; 处理JMP DS:[XXXXXXXX]的情况1000247A 8D46 06 LEA EAX,DWORD PTR DS:[ESI+6]1000247D C601 FF MOV BYTE PTR DS:[ECX],0FF10002480 C641 01 25 MOV BYTE PTR DS:[ECX+1],2510002484 ^ E9 5BFFFFFF JMP 100023E410002489 5F POP EDI1000248A C743 04 1527000>MOV DWORD PTR DS:[EBX+4],271510002491 5E POP ESI10002492 83C8 FF OR EAX,FFFFFFFF10002495 5B POP EBX10002496 83C4 10 ADD ESP,1010002499 C2 0C00 RETN 0C看完后总结一下,先把JMP API的代码跳到壳里去,IAT的处理除了mov eax,ds:[xxxxxxxx]有点不同之外,其它的都是先填入EAX的值(也就是jmp mov ebp之类的),然后写入要跳的地址,地址就是当前EIP的前一句的地址也就是eip-4,处理完就填入要返回的地址。分析完毕我们写上自己的代码;1000237A /E9 025E0000 JMP 100081811000237F |90 NOP10002380 |90 NOP10002381 |90 NOP10002382 |3D 2D8B0000 CMP EAX,8B2D10002387 |893A MOV DWORD PTR DS:[EDX],EDI10002389 |0F8F 9C000000 JG 1000242B1000238F |0F84 86000000 JE 1000241B10002395 |3D 158B0000 CMP EAX,8B151000239A |7F 68 JG SHORT 100024041000239C |74 38 JE SHORT 100023D61000239E |3D A1000000 CMP EAX,0A1100023A3 |74 1B JE SHORT 100023C0100023A5 |3D 0D8B0000 CMP EAX,8B0D100023AA |0F85 D9000000 JNZ 10002489100023B0 |E9 5C5D0000 JMP 10008111100023B5 |90 NOP100023B6 |90 NOP100023B7 |C601 8B MOV BYTE PTR DS:[ECX],8B100023BA |C641 01 0D MOV BYTE PTR DS:[ECX+1],0D100023BE |EB 24 JMP SHORT 100023E4100023C0 |E9 4C5D0000 JMP 10008111100023C5 |90 NOP100023C6 |90 NOP100023C7 |C601 A1 MOV BYTE PTR DS:[ECX],0A1100023CA |8B5424 14 MOV EDX,DWORD PTR SS:[ESP+14]100023CE |8951 01 MOV DWORD PTR DS:[ECX+1],EDX100023D1 |83C1 05 ADD ECX,5100023D4 |EB 18 JMP SHORT 100023EE100023D6 |E9 365D0000 JMP 10008111100023DB |90 NOP100023DC |90 NOP100023DD |C601 8B MOV BYTE PTR DS:[ECX],8B100023E0 |C641 01 15 MOV BYTE PTR DS:[ECX+1],15100023E4 |8B5424 14 MOV EDX,DWORD PTR SS:[ESP+14]100023E8 |8951 02 MOV DWORD PTR DS:[ECX+2],EDX100023EB |83C1 06 ADD ECX,6100023EE |2BC1 SUB EAX,ECX100023F0 |C601 00 MOV BYTE PTR DS:[ECX],0100023F3 |33C0 XOR EAX,EAX100023F5 |90 NOP100023F6 |5F POP EDI100023F7 |8941 01 MOV DWORD PTR DS:[ECX+1],EAX100023FA |5E POP ESI100023FB |33C0 XOR EAX,EAX100023FD |5B POP EBX100023FE |83C4 10 ADD ESP,1010002401 |C2 0C00 RETN 0C10002404 |3D 1D8B0000 CMP EAX,8B1D10002409 |75 7E JNZ SHORT 100024891000240B |E9 015D0000 JMP 1000811110002410 |90 NOP10002411 |90 NOP10002412 |90 NOP10002413 |90 NOP10002414 |90 NOP10002415 |90 NOP10002416 |90 NOP10002417 |90 NOP10002418 |90 NOP10002419 |90 NOP1000241A |90 NOP1000241B |E9 F15C0000 JMP 1000811110002420 |90 NOP10002421 |90 NOP10002422 |90 NOP10002423 |90 NOP10002424 |90 NOP10002425 |90 NOP10002426 |90 NOP10002427 |90 NOP10002428 |90 NOP10002429 |90 NOP1000242A |90 NOP1000242B |3D 15FF0000 CMP EAX,0FF1510002430 |7F 3D JG SHORT 1000246F10002432 |74 2C JE SHORT 1000246010002434 |2D 358B0000 SUB EAX,8B3510002439 |74 15 JE SHORT 100024501000243B |83E8 08 SUB EAX,81000243E |75 49 JNZ SHORT 1000248910002440 |B8 3D8B0000 MOV EAX,8B3D10002445 |E9 C75C0000 JMP 100081111000244A |90 NOP1000244B |90 NOP1000244C |90 NOP1000244D |90 NOP1000244E |90 NOP1000244F |90 NOP10002450 |B8 358B0000 MOV EAX,8B3510002455 |E9 B75C0000 JMP 100081111000245A |90 NOP1000245B |90 NOP1000245C |90 NOP1000245D |90 NOP1000245E |90 NOP1000245F |90 NOP10002460 |E9 AC5C0000 JMP 1000811110002465 |90 NOP10002466 |90 NOP10002467 |90 NOP10002468 |90 NOP10002469 |90 NOP1000246A |90 NOP1000246B |90 NOP1000246C |90 NOP1000246D |90 NOP1000246E |90 NOP1000246F |3D 25FF0000 CMP EAX,0FF2510002474 |75 13 JNZ SHORT 1000248910002476 |E9 965C0000 JMP 100081111000247B |90 NOP1000247C |90 NOP1000247D |90 NOP1000247E |90 NOP1000247F |90 NOP10002480 |90 NOP10002481 |90 NOP10002482 |90 NOP10002483 |90 NOP10002484 |90 NOP10002485 |90 NOP10002486 |90 NOP10002487 |90 NOP10002488 |90 NOP10002489 |5F POP EDI1000248A |C743 04 1527000>MOV DWORD PTR DS:[EBX+4],271510002491 |5E POP ESI10002492 |83C8 FF OR EAX,FFFFFFFF10002495 |5B POP EBX10002496 |83C4 10 ADD ESP,1010002499 |C2 0C00 RETN 0C然后在空地上再写一段:10008111 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10]10008115 51 PUSH ECX10008116 8BCE MOV ECX,ESI ; 填入代码到程序中10008118 3C A1 CMP AL,0A11000811A 74 34 JE SHORT 10008150 ; 对eax=a1的情况进行处理1000811C 90 NOP1000811D 9C PUSHFD1000811E 66:8BD0 MOV DX,AX10008121 66:C1E0 08 SHL AX,810008125 8AC6 MOV AL,DH10008127 9D POPFD10008128 66:8901 MOV WORD PTR DS:[ECX],AX ; 写入EAX的值1000812B 8D46 06 LEA EAX,DWORD PTR DS:[ESI+6]1000812E 8B5424 18 MOV EDX,DWORD PTR SS:[ESP+18] ; 因为前面ECX入栈了,所以这里是esp+1810008132 90 NOP10008133 90 NOP10008134 90 NOP10008135 90 NOP10008136 90 NOP10008137 90 NOP10008138 8951 02 MOV DWORD PTR DS:[ECX+2],EDX ; 填入DS:[XXXXXXXX]中的值1000813B 59 POP ECX1000813C 66:C701 0000 MOV WORD PTR DS:[ECX],0 ; 把原来填入代码给清空掉10008141 C741 02 0000000>MOV DWORD PTR DS:[ECX+2],010008148 ^ E9 9EA2FFFF JMP 100023EB ; 处理完跳回去1000814D 90 NOP1000814E 90 NOP1000814F 90 NOP10008150 8801 MOV BYTE PTR DS:[ECX],AL ; 对0A1进行处理10008152 8D46 05 LEA EAX,DWORD PTR DS:[ESI+5]10008155 8B5424 18 MOV EDX,DWORD PTR SS:[ESP+18]10008159 8951 01 MOV DWORD PTR DS:[ECX+1],EDX1000815C 59 POP ECX1000815D C601 00 MOV BYTE PTR DS:[ECX],010008160 90 NOP10008161 90 NOP10008162 C741 01 0000000>MOV DWORD PTR DS:[ECX+1],010008169 83E9 01 SUB ECX,11000816C ^ E9 7AA2FFFF JMP 100023EB ; 处理完毕跳回去10008171 90 NOP10008172 90 NOP10008173 90 NOP10008174 90 NOP10008175 90 NOP10008176 90 NOP10008177 90 NOP10008178 90 NOP10008179 90 NOP1000817A 90 NOP1000817B 90 NOP1000817C 90 NOP1000817D 90 NOP1000817E 90 NOP1000817F 90 NOP10008180 90 NOP10008181 8B5424 14 MOV EDX,DWORD PTR SS:[ESP+14] ; 这里把IAT部分放到程序里10008185 81EA 40435F00 SUB EDX,5F4340 ; 这里就是把壳的IAT地址放到我们前面新加的段里,注意,这里的值,可能每次载入后有所不同1000818B 90 NOP ; 第二次我们要手工处理一下,每二次正常过的话这里是5c4010,我们改成5C4004,并在这里下断1000818C 90 NOP ; 后面的我就用脚本来处理1000818D 90 NOP1000818E 895424 14 MOV DWORD PTR SS:[ESP+14],EDX10008192 90 NOP10008193 90 NOP10008194 90 NOP10008195 90 NOP10008196 90 NOP10008197 8B4424 20 MOV EAX,DWORD PTR SS:[ESP+20]1000819B ^ E9 E2A1FFFF JMP 10002382100081A0 90 NOP向下可以找到处理完IAT的跳:在上面也下个断,然后写脚本:var valuevar edivaluevar sedi mov value,c mov edivalue,ediand edivalue,ff000000mov sedi,edivalue run lbl1: eoe lbl2 cmp eip,100021E7 //判断有没有处理完IAT je lbl2 mov edivalue,edi //这里粗略的处理分界线 and edivalue,ff000000 cmp edivalue,sedi jne lbl3 //如果地址的前两位不同就认为是不同 add value,c lblsub: sub edx,value cmp edx,5C479C //这里对上面的粗略后留下的部分处理完 je lbl4 cmp edx,5C4B0C //找到的地址+8 je lbl4 cmp edx,5c4c40 //找到的地址+8 je lbl4 lblsub1: run jmp lbl1 lbl2: ret lbl3: mov sedi,edivalue //发现有所不同就设定一个分界线 add value,8 jmp lblsub lbl4: add edx,4 //这里也用于设定分界线 sub value,4 jmp lblsub1写完运行一下脚本,这样就可以得到很完整的程序,然后DUMP和FIXDUMP一下程序就可以运行了。好了,脱壳完毕!注意一下:程序最好不要在xp 下脱,因为那样,脱了后的文件在其它平台上可能会有问题.第二,这个壳处理IAT不是很好,所以当获取IAT失败里也不会有什么提示,这一点要我们自己去注意.抓一下成功的IAT来看看:Greetz:[align=left] Fly.Jingulong,yock,tDasm.David.ahao.UFO(brother).alan(sister).all of my friends and you![/align][align=left] [/align][align=right]By loveboom[DFCG][FCG][/align][align=right]Email:bmd2chen@tom.com[/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: