注意
本文最后更新于 2024-02-12,文中内容可能已过时。
Migrate IDA Free 8.1 Golang plugin to IDA Pro 7.7
背景
总所周知,IDA 从 8.0 开始支持 golang 1.18 的符号解析,我一直很眼馋(笑
但在一次比赛中,偶然的发现 IDA Freeware 8.0 (官网就能下)中是有该 Golang 处理器的 dll 文件的,而且该文件能够直接放到 IDA Pro 7.7 中使用,从而做到解析 golang 1.18,实现白嫖。
最近看查 IDA 文档的时候,顺便看到了 IDA 官网,发现 IDA 都更新到 8.1 版本了,又有一些新增的 golang 解析功能,于是又想着白嫖一下试试
然后我像之前一样,把新版的 golang64.dll
放置到 IDA 目录下的 plugins
文件夹,结果这次 IDA 报错了
本文就是对解决这个问题的过程,做一个记录
报错原因
该文件是我刚刚放进去的,所以文件一定是存在的,那么为什么会报错为找不到指定程序呢?
我这里最初的想法是,可能新版的 IDA 在加载过程中做了检测,如果 IDA 版本不符合则拒绝加载程序,所以导致了 dll 无法正常加载,所以应该找到 dll 中对应的检测代码,并且绕过检测即可,结果我尝试用 IDA 进行调试,发现根本没有走到 dll 的入口点,这说明肯定是加载过程中 dll 的某些数据不兼容旧版导致的,而不是内部检测,于是我着重在 LoadLibrary 的错误号 0xC0000139 进行搜索,通过搜索找到了一些信息 —— 如果加载的 DLL 的导出表信息无法找到(依赖 dll 缺少对应方法),也会导致产生 ”找不到指定的程序“ 这个错误。
所以应该转移注意到程序的导出表上,我这里用 IDA 分别打开新版和旧版的 golang64.dll 文件,Copy All
复制出对应的导出表数据,并且编写一个程序进行比对
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
| new = '''000000018000D000 RtlCaptureContext KERNEL32
000000018000D008 RtlLookupFunctionEntry KERNEL32
000000018000D010 RtlVirtualUnwind KERNEL32
000000018000D018 UnhandledExceptionFilter KERNEL32
000000018000D020 SetUnhandledExceptionFilter KERNEL32
000000018000D028 GetCurrentProcess KERNEL32
000000018000D030 TerminateProcess KERNEL32
000000018000D038 IsProcessorFeaturePresent KERNEL32
000000018000D040 QueryPerformanceCounter KERNEL32
000000018000D048 GetCurrentProcessId KERNEL32
000000018000D050 GetCurrentThreadId KERNEL32
000000018000D058 GetSystemTimeAsFileTime KERNEL32
000000018000D060 DisableThreadLibraryCalls KERNEL32
000000018000D068 InitializeSListHead KERNEL32
000000018000D070 IsDebuggerPresent KERNEL32
000000018000D080 std::_Xlength_error(char const *) MSVCP140
000000018000D090 __std_type_info_destroy_list VCRUNTIME140
000000018000D098 __C_specific_handler VCRUNTIME140
000000018000D0A0 memset VCRUNTIME140
000000018000D0A8 memmove VCRUNTIME140
000000018000D0B0 memcpy VCRUNTIME140
000000018000D0B8 _CxxThrowException VCRUNTIME140
000000018000D0C0 strstr VCRUNTIME140
000000018000D0C8 __std_exception_destroy VCRUNTIME140
000000018000D0D0 __std_exception_copy VCRUNTIME140
000000018000D0D8 __std_terminate VCRUNTIME140
000000018000D0E0 _purecall VCRUNTIME140
000000018000D0F0 __CxxFrameHandler4 VCRUNTIME140_1
000000018000D100 _callnewh api-ms-win-crt-heap-l1-1-0
000000018000D108 malloc api-ms-win-crt-heap-l1-1-0
000000018000D110 free api-ms-win-crt-heap-l1-1-0
000000018000D120 _initterm_e api-ms-win-crt-runtime-l1-1-0
000000018000D128 _initterm api-ms-win-crt-runtime-l1-1-0
000000018000D130 _seh_filter_dll api-ms-win-crt-runtime-l1-1-0
000000018000D138 _configure_narrow_argv api-ms-win-crt-runtime-l1-1-0
000000018000D140 _initialize_onexit_table api-ms-win-crt-runtime-l1-1-0
000000018000D148 _execute_onexit_table api-ms-win-crt-runtime-l1-1-0
000000018000D150 _cexit api-ms-win-crt-runtime-l1-1-0
000000018000D158 _initialize_narrow_environment api-ms-win-crt-runtime-l1-1-0
000000018000D168 strcmp api-ms-win-crt-string-l1-1-0
000000018000D170 strncmp api-ms-win-crt-string-l1-1-0
000000018000D180 read_config2 ida64
000000018000D188 hook_event_listener ida64
000000018000D190 remove_event_listener ida64
000000018000D198 get_ph ida64
000000018000D1A0 get_modctx ida64
000000018000D1A8 set_module_data ida64
000000018000D1B0 clr_module_data ida64
000000018000D1B8 get_plugin_options ida64
000000018000D1C0 set_name ida64
000000018000D1C8 validate_name ida64
000000018000D1D0 get_name_ea ida64
000000018000D1D8 copy_argloc ida64
000000018000D1E0 cleanup_argloc ida64
000000018000D1E8 set_compiler ida64
000000018000D1F0 h2ti ida64
000000018000D1F8 alloc_type_ordinals ida64
000000018000D200 build_anon_type_name ida64
000000018000D208 import_type ida64
000000018000D210 apply_tinfo ida64
000000018000D218 get_idati ida64
000000018000D220 copy_tinfo_t ida64
000000018000D228 clear_tinfo_t ida64
000000018000D230 create_tinfo ida64
000000018000D238 get_tinfo_details ida64
000000018000D240 get_tinfo_size ida64
000000018000D248 get_tinfo_pdata ida64
000000018000D250 get_tinfo_property ida64
000000018000D258 get_idasgn_desc ida64
000000018000D260 serialize_tinfo ida64
000000018000D268 get_stock_tinfo ida64
000000018000D270 save_tinfo ida64
000000018000D278 begin_type_updating ida64
000000018000D280 end_type_updating ida64
000000018000D288 get_struc_qty ida64
000000018000D290 get_struc_by_idx ida64
000000018000D298 get_struc ida64
000000018000D2A0 get_struc_id ida64
000000018000D2A8 get_struc_name ida64
000000018000D2B0 get_struc_size ida64
000000018000D2B8 add_struc ida64
000000018000D2C0 add_struc_member ida64
000000018000D2C8 get_enum ida64
000000018000D2D0 set_enum_width ida64
000000018000D2D8 get_enum_member ida64
000000018000D2E0 add_enum ida64
000000018000D2E8 create_xrefs_from ida64
000000018000D2F0 set_enum_cmt ida64
000000018000D2F8 add_enum_member ida64
000000018000D300 set_bmask_name ida64
000000018000D308 op_offset_ex ida64
000000018000D310 dirtree_mkdir ida64
000000018000D318 dirtree_rename ida64
000000018000D320 get_std_dirtree ida64
000000018000D328 under_debugger ida64
000000018000D330 callui ida64
000000018000D338 create_insn ida64
000000018000D340 get_idasgn_qty ida64
000000018000D348 plan_to_apply_idasgn ida64
000000018000D350 get_func_name ida64
000000018000D358 set_func_end ida64
000000018000D360 set_func_start ida64
000000018000D368 add_func_ex ida64
000000018000D370 set_func_cmt ida64
000000018000D378 get_func ida64
000000018000D380 bin_search2 ida64
000000018000D388 set_cmt ida64
000000018000D390 create_strlit ida64
000000018000D398 get_strlit_contents ida64
000000018000D3A0 get_max_strlit_length ida64
000000018000D3A8 create_align ida64
000000018000D3B0 create_data ida64
000000018000D3B8 get_flags_by_size ida64
000000018000D3C0 del_items ida64
000000018000D3C8 get_bytes ida64
000000018000D3D0 get_data_value ida64
000000018000D3D8 get_qword ida64
000000018000D3E0 get_dword ida64
000000018000D3E8 get_word ida64
000000018000D3F0 get_byte ida64
000000018000D3F8 is_loaded ida64
000000018000D400 get_flags_ex ida64
000000018000D408 get_item_end ida64
000000018000D410 prev_not_tail ida64
000000018000D418 next_head ida64
000000018000D420 next_that ida64
000000018000D428 add_sourcefile ida64
000000018000D430 get_segm_name ida64
000000018000D438 get_segm_by_name ida64
000000018000D440 get_first_seg ida64
000000018000D448 get_next_seg ida64
000000018000D450 getseg ida64
000000018000D458 unregister_custom_refinfo ida64
000000018000D460 register_custom_refinfo ida64
000000018000D468 set_enum_bf ida64
000000018000D470 verror ida64
000000018000D478 set_source_linnum ida64
000000018000D480 get_aflags ida64
000000018000D488 get_strid ida64
000000018000D490 netnode_supset ida64
000000018000D498 netnode_altval ida64
000000018000D4A0 netnode_check ida64
000000018000D4A8 setinf ida64
000000018000D4B0 getinf_flag ida64
000000018000D4B8 getinf_buf ida64
000000018000D4C0 getinf ida64
000000018000D4C8 qvector_reserve ida64
000000018000D4D0 qalloc_or_throw ida64
000000018000D4D8 qvsnprintf ida64
000000018000D4E0 qsnprintf ida64
000000018000D4E8 qfree ida64
000000018000D4F0 set_tinfo_property ida64
000000018000D4F8 interr ida64
'''
old = '''000000018000D000 RtlCaptureContext KERNEL32
000000018000D008 RtlLookupFunctionEntry KERNEL32
000000018000D010 RtlVirtualUnwind KERNEL32
000000018000D018 UnhandledExceptionFilter KERNEL32
000000018000D020 SetUnhandledExceptionFilter KERNEL32
000000018000D028 GetCurrentProcess KERNEL32
000000018000D030 TerminateProcess KERNEL32
000000018000D038 IsProcessorFeaturePresent KERNEL32
000000018000D040 QueryPerformanceCounter KERNEL32
000000018000D048 GetCurrentProcessId KERNEL32
000000018000D050 GetCurrentThreadId KERNEL32
000000018000D058 GetSystemTimeAsFileTime KERNEL32
000000018000D060 DisableThreadLibraryCalls KERNEL32
000000018000D068 InitializeSListHead KERNEL32
000000018000D070 IsDebuggerPresent KERNEL32
000000018000D080 std::_Xlength_error(char const *) MSVCP140
000000018000D090 __std_type_info_destroy_list VCRUNTIME140
000000018000D098 __C_specific_handler VCRUNTIME140
000000018000D0A0 memset VCRUNTIME140
000000018000D0A8 memmove VCRUNTIME140
000000018000D0B0 memcpy VCRUNTIME140
000000018000D0B8 _CxxThrowException VCRUNTIME140
000000018000D0C0 strstr VCRUNTIME140
000000018000D0C8 __std_exception_destroy VCRUNTIME140
000000018000D0D0 __std_exception_copy VCRUNTIME140
000000018000D0D8 __std_terminate VCRUNTIME140
000000018000D0E0 _purecall VCRUNTIME140
000000018000D0F0 __CxxFrameHandler4 VCRUNTIME140_1
000000018000D100 _callnewh api-ms-win-crt-heap-l1-1-0
000000018000D108 malloc api-ms-win-crt-heap-l1-1-0
000000018000D110 free api-ms-win-crt-heap-l1-1-0
000000018000D120 _initterm_e api-ms-win-crt-runtime-l1-1-0
000000018000D128 _initterm api-ms-win-crt-runtime-l1-1-0
000000018000D130 _seh_filter_dll api-ms-win-crt-runtime-l1-1-0
000000018000D138 _configure_narrow_argv api-ms-win-crt-runtime-l1-1-0
000000018000D140 _initialize_onexit_table api-ms-win-crt-runtime-l1-1-0
000000018000D148 _execute_onexit_table api-ms-win-crt-runtime-l1-1-0
000000018000D150 _cexit api-ms-win-crt-runtime-l1-1-0
000000018000D158 _initialize_narrow_environment api-ms-win-crt-runtime-l1-1-0
000000018000D168 strncmp api-ms-win-crt-string-l1-1-0
000000018000D178 read_config2 ida64
000000018000D180 hook_event_listener ida64
000000018000D188 remove_event_listener ida64
000000018000D190 get_ph ida64
000000018000D198 set_module_data ida64
000000018000D1A0 clr_module_data ida64
000000018000D1A8 get_plugin_options ida64
000000018000D1B0 set_name ida64
000000018000D1B8 validate_name ida64
000000018000D1C0 get_name_ea ida64
000000018000D1C8 copy_argloc ida64
000000018000D1D0 cleanup_argloc ida64
000000018000D1D8 set_compiler ida64
000000018000D1E0 h2ti ida64
000000018000D1E8 alloc_type_ordinals ida64
000000018000D1F0 build_anon_type_name ida64
000000018000D1F8 import_type ida64
000000018000D200 apply_tinfo ida64
000000018000D208 get_idati ida64
000000018000D210 copy_tinfo_t ida64
000000018000D218 clear_tinfo_t ida64
000000018000D220 create_tinfo ida64
000000018000D228 get_tinfo_details ida64
000000018000D230 get_tinfo_size ida64
000000018000D238 get_tinfo_pdata ida64
000000018000D240 get_tinfo_property ida64
000000018000D248 create_insn ida64
000000018000D250 serialize_tinfo ida64
000000018000D258 get_stock_tinfo ida64
000000018000D260 save_tinfo ida64
000000018000D268 begin_type_updating ida64
000000018000D270 end_type_updating ida64
000000018000D278 get_struc_qty ida64
000000018000D280 get_struc_by_idx ida64
000000018000D288 get_struc ida64
000000018000D290 get_struc_id ida64
000000018000D298 get_struc_name ida64
000000018000D2A0 get_struc_size ida64
000000018000D2A8 add_struc ida64
000000018000D2B0 add_struc_member ida64
000000018000D2B8 get_enum ida64
000000018000D2C0 set_enum_width ida64
000000018000D2C8 get_enum_member ida64
000000018000D2D0 add_enum ida64
000000018000D2D8 set_enum_bf ida64
000000018000D2E0 set_enum_cmt ida64
000000018000D2E8 add_enum_member ida64
000000018000D2F0 set_bmask_name ida64
000000018000D2F8 op_offset_ex ida64
000000018000D300 dirtree_mkdir ida64
000000018000D308 dirtree_rename ida64
000000018000D310 get_std_dirtree ida64
000000018000D318 under_debugger ida64
000000018000D320 callui ida64
000000018000D328 get_idasgn_desc ida64
000000018000D330 get_idasgn_qty ida64
000000018000D338 plan_to_apply_idasgn ida64
000000018000D340 get_func_name ida64
000000018000D348 set_func_end ida64
000000018000D350 set_func_start ida64
000000018000D358 add_func_ex ida64
000000018000D360 set_func_cmt ida64
000000018000D368 get_func ida64
000000018000D370 bin_search2 ida64
000000018000D378 set_cmt ida64
000000018000D380 create_strlit ida64
000000018000D388 get_strlit_contents ida64
000000018000D390 get_max_strlit_length ida64
000000018000D398 create_align ida64
000000018000D3A0 create_data ida64
000000018000D3A8 get_flags_by_size ida64
000000018000D3B0 del_items ida64
000000018000D3B8 get_bytes ida64
000000018000D3C0 get_data_value ida64
000000018000D3C8 get_qword ida64
000000018000D3D0 get_dword ida64
000000018000D3D8 get_word ida64
000000018000D3E0 get_byte ida64
000000018000D3E8 is_loaded ida64
000000018000D3F0 get_flags_ex ida64
000000018000D3F8 get_item_end ida64
000000018000D400 prev_not_tail ida64
000000018000D408 next_head ida64
000000018000D410 next_that ida64
000000018000D418 add_sourcefile ida64
000000018000D420 get_segm_name ida64
000000018000D428 get_segm_by_name ida64
000000018000D430 get_first_seg ida64
000000018000D438 get_next_seg ida64
000000018000D440 getseg ida64
000000018000D448 unregister_custom_refinfo ida64
000000018000D450 register_custom_refinfo ida64
000000018000D458 create_xrefs_from ida64
000000018000D460 set_source_linnum ida64
000000018000D468 get_aflags ida64
000000018000D470 get_strid ida64
000000018000D478 netnode_supset ida64
000000018000D480 netnode_altval ida64
000000018000D488 netnode_check ida64
000000018000D490 setinf ida64
000000018000D498 getinf_flag ida64
000000018000D4A0 getinf_buf ida64
000000018000D4A8 getinf ida64
000000018000D4B0 qvector_reserve ida64
000000018000D4B8 qalloc_or_throw ida64
000000018000D4C0 qvsnprintf ida64
000000018000D4C8 qsnprintf ida64
000000018000D4D0 qfree ida64
000000018000D4D8 set_tinfo_property ida64
000000018000D4E0 interr ida64'''
list = []
for i in old.splitlines():
s = i.split("\t")
list.append(s[3] + "_" + s[2])
for i in new.splitlines():
s = i.split("\t")
n = s[3] + "_" + s[2]
if n not in list:
print(n)
|
程序运行结果为
1
2
3
| api-ms-win-crt-string-l1-1-0_strcmp
ida64_get_modctx
ida64_verror
|
其中,api-ms-win-crt-string-l1-1-0_strcmp
和 ida64_verror
通过搜索能够确定是存在的,那么不能运行的原因主要就在 ida64_get_modctx
,在 ida64.dll
中,只有新版才存在这个函数,而旧版不存在。
解决思路
我想到的解决思路主要是以下两种
- 在旧版的 ida64.dll 文件中加入
get_modctx
函数 - 删除在新版的 golang64.dll 中该函数的导入表
经过简单的评估,前者需要在 dll 中插入一段代码,并且需要新增一个导出表项,但是好处在于之后如果又有版本更新,我可以直接使用新版的 dll 文件;后者则只需要删除 get_modctx
函数的相关引用,并且删除(修改)对应导入表内容为正确值。因为当天时间比较晚了,且第二天还要早 8,所以我考虑了用后者来解决这个问题
删除交叉引用
通过交叉引用搜索到新版在插件初始化中,对此处函数有如下引用
而在旧版的同样位置,这里直接赋值为 0
那思路很简单,只要 NOP CALL 并修改为 XOR RAX RAX
即可
修改后的伪代码:
修改导入表
我认为,删除一个导出表项那需要重组整个导入表,那肯定是非常麻烦的,所以我考虑修改这个导出表为其他一个已经存在的导出表函数名,因为这个函数不会被引用到,所以这样修改能保证程序正常执行。
用 DIE 可以查看对应的导入表
这里可以看到与 get_modctx
相邻的有一个 get_ph
函数,我用 010 搜索一下,并且修改值为 get_ph
即可,多余的字符串用 \x00
填充
使用 010 进行修改
修复成功
打开一个 golang 1.18 以上版本生产的程序,程序符号名称都可以正常解析了
sig
新版本中新增了很多的 sig 文件(包括新版本的 golang,MSVC 等),如果要正常的解析新版的 golang,还需要替换一下新版的 sig 文件,这里无需进行任何的修复,直接替换即可。
其他
IDA Free 8.1 的目录下,除了我所说的 golang64.dll
,实际上还有很多其他 dll
有进行更新,理论上来说,都能够通过我本文中的方法进行更改适配,不过由于其他更改对笔者来说用处不大,其他的 dll 适配就交给各位读者自行解决了。