访问数据

可以使用下面的一些方法:

idc.get_wide_byte(ea)
idc.get_wide_word(ea)
idc.get_wide_dword(ea)
idc.get_qword(ea)
idc.GetFloat(ea)
idc.GetDouble(ea)

例子:

CODE:004010CF FF 35 04 20 40 00             push    ds:hWnd                         ; hWnd
CODE:004010D5 E8 90 03 00 00                call    ShowWindow

测试方法:

print(hex(idc.get_wide_byte(idc.here())))
0xff

print(hex(idc.get_wide_word(idc.here())))
0x35ff

print(hex(idc.get_wide_dword(idc.here())))
0x200435ff

print(hex(idc.get_qword(idc.here())))
0x90e80040200435ff

GetFloat 与 GetDouble 会将地址的值强转,就不测试了。

idc.get_bytes(ea, size, use_dbg=False)可以获取从ea开始的size大小的字节,最后一个参数可选,为true表示从调试器里面获取数据,一般调试的时候,data区域数据会被修改的。

patch程序

看一个例子:

.data:1001ED3C aGcquEUdg_bUfuD db 'gcqu^E]~UDG_B[uFU^DC',0
.data:1001ED51 align 8
.data:1001ED58 aGcqs_cuufuD db 'gcqs\\_CUuFU^D',0
.data:1001ED66 align 4
.data:1001ED68 aWud@uubQU db 'WUD@UUB^Q]U',0
.data:1001ED74 align 8

这里有一些加密的字符串。

经过分析,我们找到了这些字符串的加密算法:

100012A0 push esi
100012A1 mov esi, [esp+4+_size]
100012A5 xor eax, eax
100012A7 test esi, esi
100012A9 jle short _ret
100012AB mov dl, [esp+4+_key] ; assign key
100012AF mov ecx, [esp+4+_string]
100012B3 push ebx
100012B4
100012B4 _loop: ;
100012B4 mov bl, [eax+ecx]
100012B7 xor bl, dl ; data ^ key
100012B9 mov [eax+ecx], bl ; save off byte
100012BC inc eax ; index/count
100012BD cmp eax, esi
100012BF jl short _loop
100012C1 pop ebx
100012C2
100012C2 _ret:
100012C2 pop esi
100012C3 retn

这是一个xor算法,将字符串按byte异或,key的值假设是0x42。

我们可以写脚本将字符串修改成原本的值,先用鼠标选中字符串:

start = idc.read_selection_start()
end = idc.read_selection_end()

print(hex(start))
print(hex(end))

def xor(size, key, buff):
	for index in range(0, size):
		cur_addr = buff + index
		temp = idc.get_wide_byte(cur_addr ) ^ key
		idc.patch_byte(cur_addr, temp)
		
xor(end - start, 0x30, start)
idc.get_strlit_contents(start)

get_strlit_contents 是 IDA Python 中用于获取字符串字面量内容的函数。它可以从给定的地址读取字符串数据,并处理各种字符串编码和终止符。

输入与输出