Migrate IDA Free 8.1 Golang Plugin to IDA Pro 7.7

注意
本文最后更新于 2024-02-12,文中内容可能已过时。

Migrate IDA Free 8.1 Golang plugin to IDA Pro 7.7

背景

总所周知,IDA 从 8.0 开始支持 golang 1.18 的符号解析,我一直很眼馋(笑

image-20221010173636574

但在一次比赛中,偶然的发现 IDA Freeware 8.0 (官网就能下)中是有该 Golang 处理器的 dll 文件的,而且该文件能够直接放到 IDA Pro 7.7 中使用,从而做到解析 golang 1.18,实现白嫖。

最近看查 IDA 文档的时候,顺便看到了 IDA 官网,发现 IDA 都更新到 8.1 版本了,又有一些新增的 golang 解析功能,于是又想着白嫖一下试试

image-20221010174032076

然后我像之前一样,把新版的 golang64.dll 放置到 IDA 目录下的 plugins 文件夹,结果这次 IDA 报错了

image-20221010174357225

本文就是对解决这个问题的过程,做一个记录

报错原因

该文件是我刚刚放进去的,所以文件一定是存在的,那么为什么会报错为找不到指定程序呢?

我这里最初的想法是,可能新版的 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_strcmpida64_verror 通过搜索能够确定是存在的,那么不能运行的原因主要就在 ida64_get_modctx,在 ida64.dll 中,只有新版才存在这个函数,而旧版不存在。

解决思路

我想到的解决思路主要是以下两种

  1. 在旧版的 ida64.dll 文件中加入 get_modctx 函数
  2. 删除在新版的 golang64.dll 中该函数的导入表

经过简单的评估,前者需要在 dll 中插入一段代码,并且需要新增一个导出表项,但是好处在于之后如果又有版本更新,我可以直接使用新版的 dll 文件;后者则只需要删除 get_modctx 函数的相关引用,并且删除(修改)对应导入表内容为正确值。因为当天时间比较晚了,且第二天还要早 8,所以我考虑了用后者来解决这个问题

删除交叉引用

通过交叉引用搜索到新版在插件初始化中,对此处函数有如下引用

image-20221010175947094

而在旧版的同样位置,这里直接赋值为 0

image-20221010180023086

那思路很简单,只要 NOP CALL 并修改为 XOR RAX RAX 即可

image-20221010180618690

修改后的伪代码:

image-20221010180642319

修改导入表

我认为,删除一个导出表项那需要重组整个导入表,那肯定是非常麻烦的,所以我考虑修改这个导出表为其他一个已经存在的导出表函数名,因为这个函数不会被引用到,所以这样修改能保证程序正常执行。

用 DIE 可以查看对应的导入表

image-20221010180923886

这里可以看到与 get_modctx 相邻的有一个 get_ph 函数,我用 010 搜索一下,并且修改值为 get_ph 即可,多余的字符串用 \x00 填充

使用 010 进行修改

image-20221010181104013

修复成功

打开一个 golang 1.18 以上版本生产的程序,程序符号名称都可以正常解析了

image-20221010181415986

sig

新版本中新增了很多的 sig 文件(包括新版本的 golang,MSVC 等),如果要正常的解析新版的 golang,还需要替换一下新版的 sig 文件,这里无需进行任何的修复,直接替换即可。

其他

IDA Free 8.1 的目录下,除了我所说的 golang64.dll ,实际上还有很多其他 dll 有进行更新,理论上来说,都能够通过我本文中的方法进行更改适配,不过由于其他更改对笔者来说用处不大,其他的 dll 适配就交给各位读者自行解决了。

image-20221010181633056

0%