首页
社区
课程
招聘
[原创]LordPE在win10下运行(应该叫规避win10下崩溃)
2018-12-13 22:14 7280

[原创]LordPE在win10下运行(应该叫规避win10下崩溃)

2018-12-13 22:14
7280
一直用LordPE作为PE文件分析器,习惯了。最近升级了系统到win10,发现LordPE用不了了,崩溃。后来调试发现是LordPeFix.dll的一个bug,它修改了Procs.dll,在GetNumberOfProcesses的一处call之前改大了栈缓冲区的长度参数,但缓冲区没有相应改大,于是在call中覆盖了返回地址,发生了崩溃。具体调试过程简单写一下。

用windbg调挂上LordPE_hh.exe,F5后崩溃,发现eip是一个奇怪的eip指针:

(10c04.571c): Access violation - code c0000005 (first chance)

First chance exceptions are reported before any exception handling.

This exception may be expected and handled.

eax=000000e2 ebx=00000000 ecx=76bfb79e edx=00540000 esi=75806c40 edi=0019f798

eip=000022e0 esp=0019f754 ebp=ffffffff iopl=0         nv up ei pl nz ac pe nc

cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010216

000022e0 ??              ???

k命令显示不了调用栈了:
0:000> k
 # ChildEBP RetAddr  
WARNING: Frame IP not in any known module. Following frames may be wrong.
00 0019f750 00000000 0x22e0

于是,dds esp l 100,看了一下调用栈,找到最近的LordPE主模块的调用栈:
0019fa14  004058b4 LordPE_hh+0x58b4
于是 ub 004058b4 
LordPE_hh+0x5899:
00405899 a324e54100      mov     dword ptr [LordPE_hh+0x1e524 (0041e524)],eax
0040589e 50              push    eax
0040589f 6a01            push    1
004058a1 6803100000      push    1003h
004058a6 8b0d48e64100    mov     ecx,dword ptr [LordPE_hh+0x1e648 (0041e648)]
004058ac 51              push    ecx
004058ad ffd3            call    ebx
004058af e85c060000      call    LordPE_hh+0x5f10 (00405f10)

重新加载程序,并在 004058b4 之前的call处下断点:bu  004058af,F5运行:
Breakpoint 0 hit
eax=00000000 ebx=75806c40 ecx=00345000 edx=00000000 esi=002121f0 edi=6de812f0
eip=004058af esp=0019fa18 ebp=0019fa94 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
LordPE_hh+0x58af:
004058af e85c060000      call    LordPE_hh+0x5f10 (00405f10)

F10,不进call,果然又崩溃了:
(10c04.571c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=000000e2 ebx=00000000 ecx=76bfb79e edx=00540000 esi=75806c40 edi=0019f798
eip=000022e0 esp=0019f754 ebp=ffffffff iopl=0         nv up ei pl nz ac pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010216
000022e0 ??              ???

然后重新加载,并F11跟进去继续调,发现崩溃在这个call里:
LordPE_hh+0x5f94:
00405f94 e8fb220100      call    LordPE_hh+0x18294 (00418294)
00405f99 8bf8            mov     edi,eax

重新加载进程,F11跟进去,发现进入了另一个dll的空间:procs!GetNumberOfProcesses
eax=00000000 ebx=00000000 ecx=00000000 edx=00000001 esi=75806c40 edi=0019f798
eip=00418294 esp=0019f750 ebp=ffffffff iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
LordPE_hh+0x18294:
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for E:\Tools\LPE-DLX\procs.dll - 
00418294 ff25fc924100    jmp     dword ptr [LordPE_hh+0x192fc (004192fc)] ds:002b:004192fc={procs!GetNumberOfProcesses (20001200)}

0:000> dd esp l 1
0019f750  00405f99
记下返回地址是 00405f99,此处 0019f750 下写入断点,F5运行,看是谁写坏的栈:
eax=000022e0 ebx=0019f560 ecx=0000007c edx=0002aed0 esi=0048db28 edi=00000100
eip=76bfb764 esp=0019f3e0 ebp=0019f41c iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
KERNELBASE!K32EnumProcesses+0x74:
76bfb764 8b5de0          mov     ebx,dword ptr [ebp-20h] ss:002b:0019f3fc=00450000

断下了,K命令显示一下调用栈:
 # ChildEBP RetAddr  
00 0019f41c 200012a5 KERNELBASE!K32EnumProcesses+0x74
WARNING: Stack unwind information not available. Following frames may be wrong.
01 0019f430 6de3a061 procs!GetNumberOfProcesses+0xa5

原来是 K32EnumProcesses写坏的。那么问题来了,谁调用的它?看一下返回地址处的汇编代码:
ub 200012a5
procs!GetNumberOfProcesses+0x86:
20001286 81c41c030000    add     esp,31Ch
2000128c c3              ret
2000128d 8d442404        lea     eax,[esp+4]
20001291 8d8c2430010000  lea     ecx,[esp+130h]
20001298 50              push    eax
20001299 6800040000      push    400h
2000129e 51              push    ecx
2000129f ff15ec240020    call    dword ptr [procs!GetModuleHandleEx+0x48c (200024ec)]

IDA打开procs.dll,找一下对应的位置:
.text:2000128D 8D 44 24 04                             lea     eax, [esp+220h+var_21C]
.text:20001291 8D 8C 24 30 01 00 00                    lea     ecx, [esp+220h+var_F0]
.text:20001298 50                                      push    eax
.text:20001299 68 F0 00 00 00                          push    0F0h
.text:2000129E 51                                      push    ecx
.text:2000129F FF 15 EC 24 00 20                       call    dword_200024EC

发现 20001299处的代码,文件中是push f0,但内存中却是push 400。看来有smc。

再次重新加载进程, 2000129a 处下断点内存断点,看看是谁改的代码段:
ba w1 2000129a

F5跑起来,Breakpoint 0 hit
eax=0019f8a4 ebx=00000000 ecx=00000400 edx=2000129a esi=000287dc edi=0019f8ec
eip=00022afc esp=0019f87c ebp=0019f88c iopl=0         nv up ei ng nz ac pe cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000297
LordPeFix+0x2afc:
00022afc c3              ret

往上翻看代码:
0:000> ub eip
LordPeFix+0x2aea:
00022aea c3              ret
00022aeb 668b08          mov     cx,word ptr [eax]
00022aee 8a4002          mov     al,byte ptr [eax+2]
00022af1 66890a          mov     word ptr [edx],cx
00022af4 884202          mov     byte ptr [edx+2],al
00022af7 c3              ret
00022af8 8b08            mov     ecx,dword ptr [eax]
00022afa 890a            mov     dword ptr [edx],ecx

看ecx和edx的值:
0:000> r ecx
ecx=00000400
0:000> r edx
edx=2000129a
果然是这里改了procs.dll的代码段。

回看文件中原代码,看看这次 LordPeFix 修改的意义是什么?

.text:20001291 8D 8C 24 30 01 00 00                    lea     ecx, [esp+220h+var_F0]

.text:20001298 50                                      push    eax

.text:20001299 68 F0 00 00 00                          push    0F0h

.text:2000129E 51                                      push    ecx

.text:2000129F FF 15 EC 24 00 20                       call    dword_200024EC

可以看到,ecx指向栈缓冲区,F0是这个缓冲区长度。 LordPeFix改大了缓冲区长度值,但没改大缓冲区本身。那问题就简单了,把缓冲区本身也改长一些就够了。这个缓冲区是个栈变量,是在函数开头分配的,栈空间一共分了21C字节:
.text:20001200                         GetNumberOfProcesses proc near          ; DATA XREF: .text:off_20002698o
.text:20001200
.text:20001200                         var_21C         = dword ptr -21Ch
.text:20001200                         var_218         = dword ptr -218h
.text:20001200                         var_F0          = byte ptr -0F0h
.text:20001200
.text:20001200 A1 FC 24 00 20                          mov     eax, dword_200024FC
.text:20001205 81 EC 1C 02 00 00                       sub     esp, 21Ch

LordPeFix 将F0改为400,一共改大了不到400H字节。那么我们把21C直接加上400h字节,成为61C,就足够了:
即把 sub esp, 21Ch, 改为 sub esp 61Ch。同时函数返回前别忘记把add esp,21C,改为add esp,61C,配平堆栈避免崩溃,ret指令有好几处,都要改。改完类似这个样子:
.text:20001200                 mov     eax, dword_200024FC
.text:20001205                 sub     esp, 61Ch
...
.text:20001224                 add     esp, 61Ch
.text:2000122A                 retn
...
其他的retn
...

最后对比一下改了哪几处:
fc /b PROCS_OLD.DLL PROCS.DLL
正在比较文件 PROCS_OLD.DLL 和 PROCS.DLL
00000608: 02 06
00000627: 02 06
00000650: 02 06
00000689: 02 06
000006AD: 02 06
000006BC: 02 06

OK,收工,PE编辑器又可以用了。


================================================================================
晚上又看了一下,其实是LordPeFix的一个bug,这个模块已经修改过21c为31c,不过还是改得过小。改成61c就够了。这样procs.dll就不用改了。
CODE:00403ADB                 cmp     [ebp+var_14], 21Ch
CODE:00403AE2                 jnz     loc_403F0C
CODE:00403AE8                 cmp     [ebp+var_10], 0F0h
CODE:00403AEF                 jnz     loc_403F0C
CODE:00403AF5                 cmp     [ebp+var_C], 41E660h
CODE:00403AFC                 jnz     loc_403F0C
CODE:00403B02                 mov     eax, ds:dword_4057AC
CODE:00403B07                 add     eax, 21Ch
CODE:00403B0C                 mov     [ebp+var_8], eax

DATA:004057AC dword_4057AC    dd 100h                 ; DATA XREF: Fix+E2r
DATA:004057AC                                         ; sub_403F1C+11r

上面100改为400,即21c+100改为21c+400:

正在比较文件 LordPeFix_OLD.dll 和 LORDPEFIX.DLL
00003DAD: 01 04


[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2018-12-14 21:00 被NoneName编辑 ,原因: 补漏
收藏
免费 4
打赏
分享
最新回复 (3)
雪    币: 1602
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
panti 2018-12-14 07:33
2
1
求助:运行debugview的情况下,开不了vs2017,楼主能解决一下吗?
雪    币: 12488
活跃值: (15922)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
pureGavin 2 2018-12-14 08:20
3
2
为什么我的LordPE在win10下从来就没有崩溃过,甚至还有点儿好用??
雪    币: 12843
活跃值: (9078)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
hzqst 3 2018-12-14 10:27
4
1
这个bug好像之前就有人分析过
游客
登录 | 注册 方可回帖
返回