如何解析IDA生成的汇编文件,提取函数指令助记符映射串?
问题描述
我有一份IDA Pro生成的ARM汇编文件,函数格式示例如下:
; =============== S U B R O U T I N E ======================================= release ; DATA XREF: attribute_manager_create+78↓o ; attribute_manager_create+7C↓o ... var_30 = -0x30 var_24 = -0x24 arg_0 = 0 arg_4 = 4 PUSH {R4-R9,LR} MOV R7, R0 LDR R0, [R0,#0x34] SUB SP, SP, #0x14 MOV R9, R3 LDR R3, [R0] MOV R5, R1 MOV R8, R2 BLX R3 LDR R0, [R7,#0x30] ADD R6, SP, #0x30+var_24 LDR R3, [R0,#4] BLX R3 MOV R4, R0 B loc_7A7C ; --------------------------------------------------------------------------- loc_7A70 ; CODE XREF: release+5C↓j LDR R3, [SP,#0x30+var_24] CMP R3, R5 BEQ loc_7AB4 loc_7A7C ; CODE XREF: release+38↑j LDR R3, [R4] MOV R1, R6 MOV R0, R4 BLX R3 CMP R0, #0 BNE loc_7A70 loc_7A94 ; CODE XREF: release+A0↓j LDR R3, [R4,#8] MOV R0, R4 BLX R3 LDR R0, [R7,#0x34] LDR R3, [R0,#0xC] BLX R3 ADD SP, SP, #0x14 POP {R4-R9,PC} ; --------------------------------------------------------------------------- loc_7AB4 ; CODE XREF: release+44↑j LDR R3, [SP,#0x30+arg_4] STR R3, [SP,#0x30+var_30] MOV R2, R9 LDR R3, [SP,#0x30+arg_0] LDR R6, [R5,#4] MOV R1, R8 MOV R0, R5 BLX R6 B loc_7A94 ; End of function release
需要解析该文件生成一个字典:键为函数名,值是将函数内ARM指令按指定字典映射为对应字母后拼接的字符串,不在字典中的指令直接跳过。指定映射字典如下:
arm_dict = {"MOV": "a","MVN": "b","ADD": "c","SUB": "d","MUL": "e","LSL": "f","LSR": "g","ASR": "h","ROR": "i","CMP": "j","AND": "k","ORR": "l","EOR": "m","LDR": "n","STR": "o","LDM": "p","STM": "q","PUSH": "r","POP": "s","B": "t","BL": "u","BLX": "v","BEQ": "w","SWI": "x","SVC": "y","NOP": "z"}
例如上述release函数的期望输出为:
{'release': 'randanaavncnvatjwvnnvavnnsct...'}
我之前尝试通过匹配S U B R O U T I N E和End of function标记来线性解析,但无法有效剔除指令操作数,需要示例代码或可行思路。
解决方案
核心思路
- 定位函数范围:用
; =============== S U B R O U T I N E =======================================标记函数开始,; End of function标记函数结束,只处理中间的函数内容。 - 提取函数名:在函数开始标记后的第一行非空、非注释、非变量定义的行中,取第一个单词作为函数名。
- 过滤有效指令:跳过变量定义行(如
var_30 = -0x30)、标签行(如loc_7A70)、注释行和空行,只处理包含ARM指令的行。 - 映射拼接:提取每行的指令操作码(行首的大写单词),用指定字典转换为对应字母,拼接成最终字符串。
示例Python代码
arm_dict = {"MOV": "a","MVN": "b","ADD": "c","SUB": "d","MUL": "e","LSL": "f","LSR": "g","ASR": "h","ROR": "i","CMP": "j","AND": "k","ORR": "l","EOR": "m","LDR": "n","STR": "o","LDM": "p","STM": "q","PUSH": "r","POP": "s","B": "t","BL": "u","BLX": "v","BEQ": "w","SWI": "x","SVC": "y","NOP": "z"} def parse_ida_assembly(file_path): result = {} current_func = None in_function = False current_str = [] with open(file_path, 'r') as f: for line in f: stripped_line = line.strip() # 触发函数开始解析状态 if stripped_line.startswith('; =============== S U B R O U T I N E'): in_function = True current_str = [] continue # 结束当前函数解析,保存结果 if in_function and stripped_line.startswith('; End of function'): if current_func: result[current_func] = ''.join(current_str) in_function = False current_func = None continue # 不在函数范围内则跳过 if not in_function: continue # 提取函数名:匹配函数开始后的第一个有效行 if not current_func and stripped_line and not stripped_line.startswith(';') and '=' not in stripped_line: current_func = stripped_line.split()[0] continue # 跳过变量定义、标签、注释和空行 if '=' in stripped_line or (stripped_line and stripped_line.endswith(':')) or stripped_line.startswith(';') or not stripped_line: continue # 提取指令操作码并映射 opcode = stripped_line.split()[0] if opcode in arm_dict: current_str.append(arm_dict[opcode]) return result # 使用示例 if __name__ == '__main__': output = parse_ida_assembly('your_assembly_file.asm') print(output)
代码说明
- 函数范围控制:通过两个特殊注释标记切换解析状态,确保只处理函数内部内容。
- 函数名提取:精准定位函数名所在行,避免误取注释或其他内容。
- 指令过滤:通过行特征(包含
=、以:结尾、以;开头)过滤无效行,只保留真正的指令行。 - 操作码提取:拆分指令行取第一个元素作为操作码,直接匹配映射字典完成转换。
内容的提问来源于stack exchange,提问作者Pigeoncatcher
相关产品推荐
相关产品推荐

