• 标 题:脱Flashfxp 1.3 build 780的壳 (10千字)
  • 作 者:fs0
  • 时 间:2001-8-15 22:29:59
  • 链 接:http://bbs.pediy.com

Flashfxp 1.3 build 780
http://www.billwang.net/ut/attach/159613-ffxp1.3.780.zip
fi245检测不出是用什么程序加壳,该壳绝对不亚于Asprotect,幸好该壳还算温柔,不然我的机子可惨了。

解壳程序中有不少的地方会产生异常,如:
int1
int3
div ecx ;eax=0
堆栈溢出等
只要知道Exception Handler的地址,在那里设断点就可以执行下去了,
要经常的记录有用的断点,在有走离解壳程序而出现非法操作的就从上次最近断点开始从新跟下去,一般是没问题的。
有循环的当然要注意跳过去啦,有些比较特殊的下面简单说说。

016F:005761B9  PUSHA 
016F:005761BA  CALL    005761C5
016F:005761BF  MOV      ESP,[ESP+08]
016F:005761C3  JMP      SHORT 005761DF
016F:005761C5  PUSH    DWORD [WORD FS:00]
016F:005761CB  MOV      [WORD FS:00],ESP
016F:005761D1  PUSHF 
016F:005761D2  OR      DWORD [ESP],0100
016F:005761D9  POPF   
016F:005761DA  CLC   
016F:005761DB  JNC      005761B9  ;<--这里是死循环,最终是堆栈溢出,Raise Exception
016F:005761DD  INT      20        ;xhandler 始终是 005761BF
016F:005761DF  POP      DWORD [WORD FS:00]
016F:005761E5  POP      EAX
016F:005761E6  POPA   


016F:005754D5  LEA      EAX,[EBP+046C]
016F:005754DB  SUB      BX,BX
016F:005754DE  PUSH    EAX
016F:005754DF  XOR      EAX,EAX
016F:005754E1  PUSH    DWORD [FS:EAX]
016F:005754E4  MOV      [FS:EAX],ESP
016F:005754E7  JMP      SHORT 005754F9
016F:005754E9  MOV      ESP,[ESP+08]
016F:005754ED  MOV      EBP,[ESP+08]
016F:005754F1  LEA      EAX,[EBP+048B]
016F:005754F7  PUSH    EAX
016F:005754F8  RET   
016F:005754F9  DIV      BX      ;<--Exception
016F:005754FC  JNZ      NEAR 00575622
016F:00575502  JZ      NEAR 00575622
016F:00575508  LEA      EAX,[EBP+049D]
016F:0057550E  MOV      [ESP+04],EAX
016F:00575512  MOV      [WORD FS:00],ESP
016F:00575518  JMP      SHORT 0057552A
016F:0057551A  MOV      ESP,[ESP+08]
016F:0057551E  MOV      EBP,[ESP+08]
016F:00575522  LEA      EAX,[EBP+04C2]
016F:00575528  PUSH    EAX
016F:00575529  RET   
016F:0057552A  PUSHF 
016F:0057552B  OR      DWORD [ESP],0100
016F:00575532  JNZ      00575536
016F:00575534  INT      20
016F:00575536  POPF   
016F:00575537  CLC   
016F:00575538  NOP   
016F:00575539  JNC      NEAR 00575622    ;<-- 这里不能跳,rfl c,不然就退出了
016F:0057553F  LEA      EAX,[EBP+04E1]
016F:00575545  MOV      [ESP+04],EAX
016F:00575549  MOV      [WORD FS:00],ESP
016F:0057554F  CMP      BYTE [EBP+12C7],00


下面有个循环比较难看出是哪里退出循环,这里列出来
016F:00575ABE  MOVSB 
016F:00575ABF  CALL    00575B2C
016F:00575AC4  JNC      00575ABE
016F:00575AC6  XOR      ECX,ECX
016F:00575AC8  CALL    00575B2C
016F:00575ACD  JNC      00575AE9
016F:00575ACF  XOR      EAX,EAX
016F:00575AD1  CALL    00575B2C
016F:00575AD6  JNC      00575AF8
016F:00575AD8  INC      ECX
016F:00575AD9  MOV      AL,10
016F:00575ADB  CALL    00575B2C
016F:00575AE0  ADC      AL,AL
016F:00575AE2  JNC      00575ADB
016F:00575AE4  JNZ      00575B22
016F:00575AE6  STOSB 
016F:00575AE7  JMP      SHORT 00575ABF
016F:00575AE9  CALL    00575B38
016F:00575AEE  DEC      ECX
016F:00575AEF  LOOP    00575B01
016F:00575AF1  CALL    00575B36
016F:00575AF6  JMP      SHORT 00575B20
016F:00575AF8  LODSB 
016F:00575AF9  SHR      EAX,1
016F:00575AFB  JZ      00575B48    <--跳出循环
016F:00575AFD  ADC      ECX,ECX
016F:00575AFF  JMP      SHORT 00575B1D
016F:00575B01  XCHG    EAX,ECX
016F:00575B02  DEC      EAX
016F:00575B03  SHL      EAX,08
016F:00575B06  LODSB 
016F:00575B07  CALL    00575B36
016F:00575B0C  CMP      EAX,7D00
016F:00575B11  JNC      00575B1D
016F:00575B13  CMP      AH,05
016F:00575B16  JNC      00575B1E
016F:00575B18  CMP      EAX,BYTE +7F
016F:00575B1B  JA      00575B1F
016F:00575B1D  INC      ECX
016F:00575B1E  INC      ECX
016F:00575B1F  XCHG    EAX,EBP
016F:00575B20  MOV      EAX,EBP
016F:00575B22  PUSH    ESI
016F:00575B23  MOV      ESI,EDI
016F:00575B25  SUB      ESI,EAX
016F:00575B27  REP MOVSB
016F:00575B29  POP      ESI
016F:00575B2A  JMP      SHORT 00575ABF
016F:00575B2C  ADD      DL,DL
016F:00575B2E  JNZ      00575B35
016F:00575B30  MOV      DL,[ESI]
016F:00575B32  INC      ESI
016F:00575B33  ADC      DL,DL
016F:00575B35  RET   
016F:00575B36  XOR      ECX,ECX
016F:00575B38  INC      ECX
016F:00575B39  CALL    00575B2C
016F:00575B3E  ADC      ECX,ECX
016F:00575B40  CALL    00575B2C
016F:00575B45  JC      00575B39
016F:00575B47  RET   
016F:00575B48  POP      EBP      <--跳到这里继续执行
016F:00575B49  POP      EDX
016F:00575B4A  MOV      EBX,[ESP+24]
016F:00575B4E  ADD      EBX,BYTE +10
016F:00575B51  PUSH    DWORD 4000
016F:00575B56  PUSH    EBX
016F:00575B57  PUSH    EDX
016F:00575B58  CALL    NEAR [EBP+0040AF28]


016F:00575A58  PUSH    EAX
016F:00575A59  PUSH    ECX
016F:00575A5A  CALL    00575A79
016F:00575A5F  CMP      EAX,BYTE -01
016F:00575A62  JZ      NEAR 00575C86
016F:00575A68  ADD      EDI,BYTE +0C
016F:00575A6B  DEC      ESI          <--这里的ESI可能是原程序的Section数
016F:00575A6C  JNG      00575A74      <--还原完就跳
016F:00575A6E  JMP      NEAR [EBP+0040A1D0]
016F:00575A74  JMP      00575B77


;=======================================================================
其生成输入表的重定向代码如下
016F:00870000 FF358E018700    PUSH    DWORD [0087018E]  ;<-- [0087018E] 放的是 Import Function Address
016F:00870006 3CC3            CMP      AL,C3
016F:00870008 C3              RET   
016F:00870009 FC              CLD   
016F:0087000A FF3592018700    PUSH    DWORD [00870192]
016F:00870010 F6C1C3          TEST    CL,C3
016F:00870013 C3              RET   
016F:00870014 FF3596018700    PUSH    DWORD [00870196]
016F:0087001A A8C3            TEST    AL,C3    ;<-- 无用代码?
016F:0087001C 90              NOP   
016F:0087001D C3              RET   



下面是解壳程序Import table重建的部分代码
016F:00575C16  MOV      EDX,[EBP+0040AFBE]
016F:00575C1C  MOV      ESI,[EBP+0040AFAE]
016F:00575C22  TEST    ESI,ESI
016F:00575C24  JZ      NEAR 00575FC7
016F:00575C2A  ADD      ESI,EDX
016F:00575C2C  AND      DWORD [EBP+0040B0AA],BYTE +00
016F:00575C33  MOV      EAX,[ESI+0C]
016F:00575C36  AND      DWORD [ESI+0C],BYTE +00
016F:00575C3A  TEST    EAX,EAX
016F:00575C3C  JZ      NEAR 00575FC7    ;<-- 处理完全部dll没有?
016F:00575C42  ADD      EAX,EDX
016F:00575C44  MOV      EBX,EAX
016F:00575C46  PUSH    EAX
016F:00575C47  CALL    NEAR [EBP+0040AF18]


016F:00575DE3  MOV      [ESP],EBX
016F:00575DE6  MOV      AX,35FF      ;<-- PUSH 的代码,改为 MOV EAX,25FF
016F:00575DEA  PUSH    DWORD 00C3C1F6
016F:00575DEF  PUSH    DWORD C3A8C33C
016F:00575DF4  PUSH    DWORD 0035FF80
016F:00575DF9  PUSH    DWORD 90FCF9F8
016F:00575DFE  PUSH    BYTE +00
016F:00575E00  STOSW 
016F:00575E02  INC      DWORD [ESP]  ;<-- 已处理的Import functions数
016F:00575E05  MOV      [EDI],EBX    ;<-- ebx 是Import functions的地址
016F:00575E07  ADD      EBX,BYTE +04
016F:00575E0A  ADD      EDI,BYTE +04
016F:00575E0D  AND      DWORD [ESP],BYTE +03
016F:00575E11  CMP      DWORD [ESP],BYTE +00
016F:00575E15  JZ      00575E45
016F:00575E17  CMP      DWORD [ESP],BYTE +01
016F:00575E1B  JZ      00575E4D
016F:00575E1D  CMP      DWORD [ESP],BYTE +02
016F:00575E21  JZ      00575E6A
016F:00575E23  ROL      DWORD [ESP+0C],10
016F:00575E28  MOV      AX,[ESP+0C]      ;<-- 随机无用代码?
016F:00575E2D  STOSW 
016F:00575E2F  MOV      EAX,EBX
016F:00575E31  SHR      EAX,03
016F:00575E34  AND      EAX,BYTE +03
016F:00575E37  MOV      AL,[ESP+EAX+04]
016F:00575E3B  STOSB 
016F:00575E3C  MOV      AL,C3          ;<-- RET 代码
016F:00575E3E  STOSB 
016F:00575E3F  MOV      AX,35FF        ;<-- PUSH 的代码,改为 MOV EAX,25FF
016F:00575E43  JMP      SHORT 00575E72
016F:00575E45  MOV      EAX,[ESP+08]
016F:00575E49  STOSD 
016F:00575E4A  DEC      EDI
016F:00575E4B  JMP      SHORT 00575E3C
016F:00575E4D  MOV      AX,[ESP+0C]
016F:00575E52  STOSW 
016F:00575E54  MOV      AL,C3
016F:00575E56  STOSB 
016F:00575E57  MOV      EAX,EBX
016F:00575E59  SHR      EAX,03
016F:00575E5C  AND      EAX,BYTE +03
016F:00575E5F  MOV      AL,[ESP+EAX+04]
016F:00575E63  STOSB 
016F:00575E64  MOV      AX,35FF        ;<-- PUSH 的代码,改为 MOV EAX,25FF
016F:00575E68  JMP      SHORT 00575E72
016F:00575E6A  MOV      EAX,[ESP+10]
016F:00575E6E  STOSD 
016F:00575E6F  DEC      EDI
016F:00575E70  JMP      SHORT 00575E3C
016F:00575E72  LOOP    00575E00        ;<--该dll处理完没有
016F:00575E74  STOSW 
016F:00575E76  ADD      ESP,BYTE +14
016F:00575E79  POPA   
016F:00575E7A  MOV      [EBP+0040B0AA],EDI
016F:00575E80  MOV      EDI,[EBP+0040B0AA]  ;<--下面是GetProcAddress, 放到EDI指向的地方
016F:00575E86  MOV      EAX,[EBP+0040B0B2]
016F:00575E8C  ADD      EAX,[EBP+0040AFAA]
016F:00575E92  MOV      ECX,[EBP+0040B0AE]
016F:00575E98  MOV      [EAX],ECX
016F:00575E9A  ADD      DWORD [EBP+0040B0AE],BYTE +0A
016F:00575EA1  JMP      SHORT 00575EAB



下面我们要重建Import Table

016F:00870000 FF358E018700    PUSH    DWORD [0087018E]
016F:00870006 3CC3            CMP      AL,C3
016F:00870008 C3              RET   
上面的代码用Import REConstructor v1.2并不能识别,经过上面的分析,
我们可以将PUSH DWORD [0087018E] 改为 JMP DWORD [0087018E],Import REConstructor就可以重建,
将 FF35 改为 FF25 就行了
;=======================================================================


再过不远就到
016F:005760EB  LEA      EDI,[EBP+0040AEB0]
016F:005760F1  XOR      EAX,EAX
016F:005760F3  MOV      ECX,02C0
016F:005760F8  REP STOSB        ;<-- 清除上面的代码
016F:005760FA  LEA      EDI,[EBP+00409B68]
016F:00576100  MOV      ECX,1105
016F:00576105  REP STOSB        ;<-- 清除上面的代码
016F:00576107  STOSW 
016F:00576109  LEA      EDI,[EBP+00409B68]
016F:0057610F  TEST    ESI,ESI
016F:00576111  JNZ      0057611B
016F:00576113  MOV      DWORD [EDI],C340C033
016F:00576119  JMP      SHORT 00576126
016F:0057611B  MOV      BYTE [EDI],E9
016F:0057611E  INC      EDI
016F:0057611F  SUB      EBX,EDI
016F:00576121  SUB      EBX,BYTE +04
016F:00576124  MOV      [EDI],EBX
016F:00576126  LEA      EDI,[EBP+0040AC6D]
016F:0057612C  MOV      ECX,2C
016F:00576131  REP STOSB        ;<-- 清除上面的代码
016F:00576133  STOSW 
016F:00576135  JMP      SHORT 00576139
016F:00576137  INT      20
016F:00576139  POPA   
016F:0057613A  JMP      NEAR [ESP-30]  ;<--Jump to OEP