用x32/x64dbg脱DLL壳(IAT表修复和重定位表修复)

exe脱壳

一直搜到的都是看雪论坛上用的lordPE和ImportREC进行脱壳和修复,感觉有点过时了.
记录一下x32/x64dbg的脱壳和IAT修复方法.
首先用esp定律等方法找到程序的入口点, 然后使用Scylla插件并填写其中的OEP地址.
在这里插入图片描述
然后用IAT Autosearch去找可能的IAT表,dump并fix pe文件即可.
在这里插入图片描述

DLL 脱壳

和exe脱壳不同, exe因为是第一个装载的模块,因此不需要进行重定位操作,它的base地址一定在0x400000. 但是DLL因为装载的冲突,会需要进行重定位,如果脱壳后重定位表缺失,重定位发生错误. 不过这个错误也不是一定会发生,万一DLL就装载到它原本预设的ImageBase处了,那么这时候没有reloc表也没有关系了(具体做法呢就是多重启几遍hh) .
当然这样重启很烦,所以DLL的脱壳会比exe多一步: 进行reloc表的修复.
基于《加密与解密》这本书的方法, 我们在壳代码中找到壳是怎么修复重定位表的.
首先看一下描述重定位表的结构体:

IMAGE_BASE_RELOCATION STRUCT
	VirtualAddress dd 0
	SizeOfBlock    dd 0
	Type1          dw 0 ; Bit15~Bit12 为type , Bit11~Bit0为Itemoffset
IMAGE_RELOCATION ENDS

VirtualAddress 是用来决定地址的Bit15~Bit12(它的后12位都是0), 而Type1决定了 Bit11~Bit0.
假设我们的dll文件内的ImageBase是0x560000, 但是真实的装载地址在0x7f0000, 那么rebase时就按照ImageBase+VirtualAddress+Itemoffset + (0x7f0000-0x560000)来计算重定位后的地址. 重定位表事实上就是由IMAGE_BASE_RELOCATION 结构体数组组成的. 这些数组中的VirtualAddress 值依次递增.
在脱壳时可以在需要重定位的地址下硬件断点,找到壳代码还原重定位表的地方:
在这里插入图片描述
然后在这段代码往上翻翻,能找到重定位表和结构体中VirtualAddress的值.
在这里插入图片描述
因此在上面的两张图中下断点,每次hit的时候第一张图打印edi, 第二张图打印eax的值, 分别可以获得IMAGE_BASE_RELOCATION 结构体中的Itemoffset 和 VirtualAddress.
重复运行以后,可以在x32dbg的日志中获得类似如下结构的文本:

eax:1000
591B57
591BD7
591BE4
...
eax:2000
592E00
592E16
...
eax:3000
593E68
593E6C

然后就可以写个python脚本修复一下啦!

import math
def find_pe_header(dll:bytearray):
    return int.from_bytes(dll[0x3c:0x40],'little')
def find_base_reloction_tbl(dll,pe_header):
    if(int.from_bytes(dll[pe_header+0x14:pe_header+0x16],'little') == 0xe0): #PE32
        return pe_header+0xa0
    elif (int.from_bytes(dll[pe_header+0x14:pe_header+0x16],'little') == 0xf0): #PE32+
        return pe_header+0xb0
    else:
        raise RuntimeError

def find_section_reloc_header(dll:bytearray):
    return  dll.index(b'.reloc\x00\x00')

with open('DllSample_dump_SCY.dll','rb') as f:
    dll = bytearray(f.read())

# find pe_header
pe_header = find_pe_header(dll)

 #修改.reloc段中的PointertoLawData到文件最后我们新建的重定位表上
section_reloc_header = find_section_reloc_header(dll)
dll[section_reloc_header+20:section_reloc_header+24] = len(dll).to_bytes(4,'little')

with open('reloc.txt','r') as f:
    data = f.read().split('\n')
base_relocation_map = {}
for x in data:
    if 'eax' in x:
        b = int(x[4:],16)
        base_relocation_map[b]=[]
    else:
        x = int(x,16)
        base_relocation_map[b].append(x&0x000fff|0x003000)
size = 0
for k,v in base_relocation_map.items():
    blocksize = math.ceil((8+len(v)*2)/4)*4 
    size += blocksize
    new_reloc = k.to_bytes(4,'little')+blocksize.to_bytes(4,'little')
    for data in v:
        new_reloc += data.to_bytes(2,'little') 
    new_reloc += b'\x00'*(blocksize-8-len(v)*2) #4字节对齐
    dll += new_reloc

#file_alignment对齐
file_alignment = int.from_bytes(dll[pe_header+0x18+0x3c:pe_header+0x18+0x3c+4],'little')
dll += b'\x00'*(file_alignment-len(dll)%file_alignment) 
# 修改重定位表大小
base_reloc_tbl = find_base_reloction_tbl(dll,pe_header)
dll[base_reloc_tbl+4:base_reloc_tbl+8] = size.to_bytes(4,'little') 
# 修改SizeofRawData
dll[section_reloc_header+16:section_reloc_header+20]  = (math.ceil(size/file_alignment)*file_alignment).to_bytes(4,'little') 

with open('DllSample.dll','wb') as f:
    f.write(dll)
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值