0%

和特征码插件配套的IDA搜索脚本以及使用技巧

效果

图片1

例子

  • 智能判断一些东西

  • 这里以ObjManager为例子
    图 1

  • 快捷键 x查找引用

  • 找到代码引用地址

  • 使用 PatternGen 生成特征码

    1
    2
    3
    4
    5
    6
    7
    tp3:005297B4                 mov     ecx, ds:ObjManager
    .tp3:005297BA call sub_6A3FA0
    .tp3:005297BF push eax
    .tp3:005297C0 call sub_5A9F90
    .tp3:005297C5 add esp, 4
    .tp3:005297C8 retn 4
    .tp3:005297C8 sub_5297B0 endp
    1
    8B ?? ?? ?? ?? ?? E8 ?? ?? ?? ?? 50 E8 ?? ?? ?? ?? 83 ?? ?? C2
    1
    FindOffsetValue('8B ?? ?? ?? ?? ?? E8 ?? ?? ?? ?? 50 E8 ?? ?? ?? ?? 83 ?? ?? C2')
  • 调用搜索函数这里会自动判断操作数 这里返回的就是ObjManager

  • 如果是函数调用 比如 E8 xxx 这里就是返回E8 目标地址

  • 而非函数也非操作数 则会返回特征码所特征函数头部

  • 反正说也说不清 用了才知道

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# coding=utf-8
from idautils import XrefsTo
from idc import BADADDR, INF_BASEADDR, SEARCH_DOWN, FUNCATTR_START, FUNCATTR_END
import idc
import idaapi
import datetime


def MakeEnum(enumName, offsetArray):
print ("enum class %s\r\n{" % enumName)
for offset in offsetArray:
if len(offset[0]) == 0:
print ("")
continue
if type(offset[1]) is str:
print (" %s = %s," % (offset[0], offset[1]))
continue

'''
fncValue = offset[1] if offset[1] != -1 else 0x0
'''
# print " %s = 0x%08x,%s" % (offset[0], fncValue, ' // Unknown' if fncValue == 0x0 else '')

fncValue = offset[1] if offset[1] != -1 else 0x0

locByName = idc.LocByName(offset[0])
isMismatch = locByName != fncValue

if locByName == BADADDR:
locByName = fncValue

print (" %s = 0x%08x,%s" % (offset[0], locByName, '// Possible mismatch' if isMismatch else ''))

print ("};\r\n")


def MakeNamespace(name, offsetArray):
# type: (object, object) -> object
print ("namespace %s \n{" % name)
for offset in offsetArray:
of = 0
if offset[1] != 0:
of = offset[1] - idaapi.get_imagebase()
print("\tconst auto %-20s = 0x%X;\t//0x%X" % (offset[0], of, offset[1]))
print("};\r\n")


def FindFunctionByPatternStartEA(pattern):
address = idc.FindBinary(0, SEARCH_DOWN, pattern)
if address == BADADDR:
return BADADDR

try:
return idaapi.get_func(address).startEA
except Exception:
return -1


def FindOffsetValue(pattern, offset=0):
if pattern == '':
return 0
try:
address = idc.FindBinary(0, SEARCH_DOWN, pattern) + offset
op1 = idc.GetOpType(address, 0)
op2 = idc.GetOpType(address, 1)

if idc.Byte(address) == 0xE8:
if op1 == idc.o_near and op2 == idc.o_void:
return idc.GetOperandValue(address, 0)
elif op1 == idc.o_reg and (op2 == idc.o_mem or op2 == idc.o_imm) and idc.Byte(address) != 0x83:
return idc.GetOperandValue(address, 1)
elif (op1 == idc.o_mem or op1 == idc.o_imm) and op2 == idc.o_reg and idc.Byte(address) != 0x83:
return idc.GetOperandValue(address, 0)
else:
return idaapi.get_func(address).startEA

except Exception:
return 0


def GetStr(ea):
Version = ""
i = 0
while True:
bt = idc.Byte(ea + i)
i = i + 1
if bt != 0:
Version = Version + chr(bt)
else:
return Version
# oObjChampionName->A1 ? ? ? ? 05 ? ? ? ? 5B
# #define oObjAttackRange 0x1484 //D8 81 ? ? ? ? 8B 81 ? ? ? ?
def main():
print("//[*] League of Legends Client Update Tool")
print("//[*] By Chord")
print("//[*] Started at: %s" % datetime.datetime.now())
print("//----------------------------")

MakeNamespace('GameClass', [
["GameTime", FindOffsetValue('F3 0F 11 05 ? ? ? ? 8B 49')],
# ["BuildVersion", FindOffsetValue('8B 44 24 04 BA ? ? ? ? 2B D0', 4)],
["ObjManager", FindOffsetValue('8B 0D ? ? ? ? E8 ? ? ? ? FF 77')],
["LocalPlayer", FindOffsetValue('A1 ?? ?? ?? ?? 85 C0 74 07 05 ?? ?? ?? ?? EB 02 33 C0 56')],
["ChatClient", FindOffsetValue('8B ?? ?? ?? ?? ?? 6A ?? 50 E8 ?? ?? ?? ?? 33 C0 5F C2')],
["MenuGuiIns", FindOffsetValue('8B 0D ? ? ? ? 6A 00 E8 ? ? ? ? C7')],
["HudInstance", FindOffsetValue('A1 ? ? ? ? 83 78 08 02 0F 94 C0')],
["PingInstance", FindOffsetValue('8B 0D ? ? ? ? 85 C9 74 07 8B 01 6A 01 FF 50 08 8B')],
])
MakeNamespace('Function', [
["GetPing", FindOffsetValue('E8 ? ? ? ? 8B 44 24 1C 83 C4 0C 8B CE')],
["IsAlive", FindOffsetValue('56 8B F1 8B 06 8B 80 ? ? ? ? FF D0 84 C0 74 19')],
["IsMissile", FindOffsetValue('E8 ?? ?? ?? ?? 83 C4 04 84 C0 74 60')],
["IsTargetable", FindOffsetValue('E8 ? ? ? ? 8B F8 8B CB 89 ')],
["IssueOrder", FindOffsetValue('E8 ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B 84 ?? ?? ?? ?? ?? 8B CF F3 0F 7E 00')],
["GetFirstObj", FindOffsetValue('8B 41 14 8B 51 18')],
["GetNextObj", FindOffsetValue('E8 ? ? ? ? 8B F0 85 F6 75 E4')],
["GetSpellState", FindOffsetValue('E8 ? ? ? ? 8B F8 8B CB 89')],
["SendChat", FindOffsetValue('E8 ? ? ? ? 8D 4C 24 04 C6')],
["PrintChat", FindOffsetValue('E8 ? ? ? ? 33 C0 5F C2')],
["GetHpBarPos", FindOffsetValue('E8 ?? ?? ?? ?? 8B 4E ?? 8D 54 ?? ?? 52 8B 01 FF ?? ?? 5E 83 ?? ?? C3')],
["GetAiManager", FindOffsetValue('E8 ?? ?? ?? ?? 50 8B CE E8 ?? ?? ?? ?? 80 BB ?? ?? ?? ?? ??')],
["WorldToScreen", FindOffsetValue('83 EC 10 56 E8 ? ? ? ? 8B 08')],
["BaseDrawPosition", FindOffsetValue('E8 ?? ?? ?? ?? EB ?? 8B 01 8B 40')],
["GetAttackDelay", FindOffsetValue('E8 ? ? ? ? 8B 44 24 1C 83 C4 0C 8B CE ')],
["GetAttackCastDelay", FindOffsetValue('E8 ?? ?? ?? ?? D9 ?? ?? ?? ?? ?? 56 E8')],
["SetBaseCharacterData", FindOffsetValue('E8 ?? ?? ?? ?? 8B 54 ?? ?? 83 ?? ?? 72 ?? 8B 4C ?? ?? 42 8B C1 81 ?? ?? ?? ?? ?? 72 ?? 8B 49 ?? 83 ?? ?? 2B C1 83 ?? ?? 83 ?? ?? 0F ?? ?? ?? ?? ?? 52 51 E8 ?? ?? ?? ?? 83 ?? ?? 8B 06 8B CE FF ?? ?? ?? ?? ?? 8B CE F3 0F')],
["OnCreateObject", FindOffsetValue('E8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 74 ?? 32 C9 EB')],
["OnDeleteObject", FindOffsetValue('E8 ?? ?? ?? ?? 57 E8 ?? ?? ?? ?? 83 ?? ?? 5F 5E C3')],
["OnProcessSpell", FindOffsetValue('E8 ?? ?? ?? ?? 8B CE E8 ?? ?? ?? ?? 80 BE ?? ?? ?? ?? ?? D8')],
])


if __name__ == '__main__':
main()