ManyJmp.exe程序的分析:
Crtl+N可以查看输入表
按名称排列的结果:
首先对dll分类,同dll的放到一起,再按名称排列
Kernel32都是关于核心的一些函数
User32包含弹框之类的
因为程序对错误的判断是通过的弹框,因此对MessageBox类函数查找
找不到!!!
DestroyWindow也一样,找不到;
–{这些函数有可能是动态加载的比如之前遇到的 看雪pwn实验中loadlibrary()函数调用user32.dll但是用dependency walker无法找到*【动态加载】*}
使用IDA对程序反编译,轻松找到main函数
再对程序的主要逻辑进行跟踪调试
C++:xxx::cout表示输出/cin表示输入
程序首先判断了长度是否为0x26
然后进入了一个主要逻辑:
Call 00401e10处就是manyjmp题目的主要部分了
走一步一个jmp,非常烦
该函数做完后,调用了sleep函数,将程序挂起3秒。
因此猜测有另一个线程
不然程序闲的蛋疼突然睡觉睡那么久
函数401e10(核心manyjmp):
编程对程序进行提取:
Jmp [0x12345678] 的机器码总是为
->FF25 78563412
而再jmp之前就是需要提取的指令,由于提取的指令的长度是不一定的,因此可以选择对代码进行扫描,一旦发现ff25,就将之前的几个字节保存为需要的代码,然后对ff25之后的4个字节保存为一个32位地址指针p,那么将要跳向的地址就是p,到达p后,再次开始计数,直到遇到ff25,将之前的指令保存提取,依次循环
调试发现循环的结束是一个ret指令,机器码位C3,那么同样的,再之前的扫描循环中加入对是否位ret指令的判断
–{dump范围:400000+length;length可以使用最后一个代码段的rva,在加上最后一个代码段的长度,注意保证对齐,也就是说最后获得的东西一般是0x1000的倍数~}
面临的问题:
在提取的代码中很有可能会出现相对跳转如jbe,这种跳转指令的解释模式并不是直接寻址,而是利用相对的偏移地址进行跳转的,一旦我们将提取的指令放到一起来执行的话,相当于大幅度压缩了代码的长度,利用相对偏移进行的跳转就会失效!
解决方案:
改变原指令,减小偏移跳转的值;
在提取每一条指令的时候输出该指令的原地址偏移以及提取后的新偏移,
例:jbe 1000指令提取
提取后所对应的压缩的指令块中的新偏移为56
定位到该指令,修改汇编代码为jbe 56(可以直接写56,偏移他会自己算的)
将获得的代码块load到原函数处,覆盖那个垃圾jmp
然后就好读的多了~
发现里面是base64的一个变形算法,取6位的方式与原base64相反,是大端的方式取
–{base64简介:每6位一组,小端取,很诡异,看讲义吧}
看完这部分的算法后,就差不多开始去看另一个线程了~