加壳与脱壳----壳的原理

PE结构体

1 PE文件结构图

 

 

PE文件用硬盘到能运行起来经历的步骤

1 将pe文件copy到内存

2 按内存对齐值对齐

3 加载dll

4 修复 IAT、重定位表

程序允许

操作系统通过读取PE文件的addressOfEntryPoint(OEP)+PE文件的imagebase加载基址位置开始执行代码

壳的原理

修改OEP将OEP指向自己的壳代码所在的地址运行,执行完后再跳回真正的OEP

难点:

1 代码放在哪里

放在可执行的区段里面,可以查看区段头看execute属性是否为1,

当然.text区段通常是可行的,因为.text代表的是代码段

那么代码如何放呢?肯定是不能覆盖原有的东西,需要在新的空白的地方来代码,通常由于对齐的原因,所以会有空白的地方产生,就在空白的地方写代码就好了

 

 

 

2 代码怎么写--shellcode

假设这里要写一个弹出MessageBoxA

就很简单

push 0      6A 00
push 0 6A 00
push 0 6A 00
push 0 6A 00
call MessageBoxA E8 xxxxxxx

E8 xxxx的硬编码等于两个函数地址偏移值-5

3 如何回到原始OEP 直接jmp回去就好了

jmp oep         E9 xxxxxxx

E9 xxxx后面的硬编码等于地址相减再减2

Hello Shell--代码编写

对一个简单的exe添加壳,在调用exe前先调用一个壳代码,然后再返回执行正常的exe代码逻辑

1 找到要调用的MessageBoxA地址

因为这里要调用的是MessageBoxA的地址

所以这里我直接通过分析客户端找到了一个MessageBoxA的地址

 

 

直接在od里面输入API名称,然后就可以得到首地址,这里我的首地址是

0x74B61930

得到call 的硬编码

call xxxx

得硬编码对应的应该是E8 yyyyy

这里的yyyy = 要调用的函数的地址-当前地址-5的值

所以这里需要得到call这个指令的内存地址

这里的话直接通过loadPE,查找.text区段找到我们要实现存放硬编码的地址处理就好了

 

 

这里的黑色的范围就都是.text的范围

这里我选择0x00000850来处理

但是需要注意的是,这个是文件中的偏移地址FOA,需要计算成内存中的编译地址VOA才行

这里继续可以用LoraPE里面的

 

 

拿到VA就好了

拿到VA后,MessageBoxA-VA-5 = call后面的硬编码地址

2 得到jmp的地址

同样jmp 是E9 xxx

这个xxx的地址也和上一个call xxx的硬编码所求的方法一样

3 通过010 Editor修改

修改对应的位置的硬编码的值,来修改OEP先到MessageBoxA哪里,再执行跳转Jmp 回到OEP