基于ImmDbg的Python内存注射

其实上一篇文章完全是拷贝来的,目的是做个本地备份。 😀 最近开始将一些工作转移到ImmDbg,在此之前是想在OD的脚本中做一些简单的工作来实现一些内存数据的修改以及写入功能,但是事实上由于OD脚本的API函数有限,要实现诸如文件读取之类的工作发现基本没什么可能,当然了也有可能是因为自己孤陋寡闻, :8 如果谁知道相关的APi还望不吝赐教。 smile

 

而ImmDbg则很好的弥补了这一点,因为即使ImmDbg的Python Lib没有提供相关的诸如文件从操作之类的函数,那么也可以很简单引入一些其他的库来实现相关的功能。需要说明的是俺不是专业的Python开发工程师,甚至连门都没入,于是只能边搜索边实现。当然经过俺的东拼西凑最终实现的脚本还是能够正常工作的。本来是想把上一篇文章翻译成中文的,但是后来放弃鸟,为虾米?因为俺懒呗。 smile

也不知道是神马原因,ImmDbg提供的帮助文档,在我这里打开之后发现神马内容都木有。这让俺很受伤嗫 sad

好了,不多说废话鸟。开始正文,python读取二进制文件还是比较简单的,代码也是简单的两行:

1
2
rcFileHandle = open ('C:\\afs.rs','rb')
rcFileData = rcFileHandle.read()

通过这两行代码就把文件读取到内存中了,但是如果这时候去内存中找这个东西就会发现根本找不到。通过python id()函数可以查看变量的地址,但是如果在调试进程中去找这个地址就会发现找到的东西和加载的数据完全不同。由于对Python的机制不了解,所以这个数据加载到了哪个进程中的这个地址也不甚了然,如果哪位大侠知道还望不吝赐教。

将数据加载到内存之后就可以使用imm库中的writeMemory方法了,函数原型:

1
2
3
4
5
6
7
8
9
10
11
def writeMemory(self, address, buf):
"""
Write buffer to memory address.
 
@type address: DWORD
@param address: Address
 
@type buf: BUFFER
@param buf: Buffer
"""
return debugger.write_memory(buf, address, len(buf), 0x2)

该函数并没有定义数据长度,但是在实现的方法中使用len函数取得传入数据的长度。如果要写入的数据比该内存中的原始数据长度要大则会写入失败。当确实需要写入较多的数据的时候就变得比较蛋疼了,所以可以采用变通的方法来修改指针地址,可以使用如下的方法修改函数指针:

1
2
3
4
5
6
7
8
9
10
11
def writeLong(self, address, dword):
"""
Write long to memory address.
 
@type address: DWORD
@param address: Address
 
@type dword: DWORD
@param dword: long to write
"""
return debugger.write_memory( immutils.intel_order( dword ), address, 4, 0x2 )

通过原型也可以发现写入指针地址也比较简单,现在需要的就是分配一个内存将读入的数据复制到申请的堆栈中:

1
rcTmpRcaddr = imm.rVirtualAlloc(rcMemDataAddr,rcFileLength *2,0x00001000,0x40)

rVirtualAlloc也是一个比较难疼的API,在非常多的情况下都会申请失败,函数原型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def rVirtualAlloc(self, lpAddress, dwSize, flAllocationType, flProtect):
"""
Virtual Allocation on the Debugged Process
 
@type lpAddress: DWORD
@param lpAddress: Desired starting Address
 
@type dwSize: DWORD
@param dwSize: Size of the memory to be allocated (in bytes)
 
@type flAllocationType: DWORD
@param flAllocationType: Type of Memory Allocation (MEM_COMMIT, MEM_RESERVED, MEM_RESET, etc)
 
@type flProtect: DWORD
@param flProtect: Flag protection of the memory allocated
 
@rtype: DWORD
@return: Address of the memory allocated
"""
return debugger.pVirtualAllocEx( lpAddress, dwSize, flAllocationType, flProtect )

lpAddress定义了内存申请的起始地址,这个地址如果从0开始比较容易失败,所以最好从断点所在的内存空间中申请,成功率会高一些。

在把从文件中的数据写入到新申请的内存中就可以将新的内存地址覆盖到要修改的指针的地址就可以了。这样也就避免了直接写入内存不足的问题。

通过上面的方法同样可以自定义一些shellcode用这种方式加载到内存中,然后跳转过去执行即可。

相比于OD的插件开发,和功能较少的脚本APi使用Python显然是个不错的选择。当然可能内存注射也不够准确,只是实现内存数据的修改以及注入而已。

如果谁知道Pyhon读取文件加载的地址在什么地方还望不吝赐教。 

You may also like

发表评论

电子邮件地址不会被公开。 必填项已用*标注