首页
社区
课程
招聘
[分享]IDAPython---未识别函数创建
发表于: 2023-9-9 09:09 4404

[分享]IDAPython---未识别函数创建

2023-9-9 09:09
4404

IDAPython---未识别函数创建

keywords: ida python 创建函数

有时候IDA不能自动识别一些函数,指令都是红色的,虽然可以自己一个个创建函数,但是太慢了,所以用脚本实现一下,创建有明显开头特征的函数。

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
import idautils
import idc
import idaapi
import ida_search
 
print("脚本开始执行")
 
# "push ebp" 的机器码是 55
# "mov ebp, esp" 的机器码是 8B EC 或者 89 E5
patterns = [
    "55 8B EC",
    # 4029f9fcba1c53d86f2c59f07d5657930bd5ee64cca4c5929cbd3142484e815a
    # https://malware.news/t/api-hashing-in-the-zloader-malware/40695
    "55 89 E5",
]
 
# 遍历所有的代码段
for seg_ea in idautils.Segments():
    # 获取段的名称
    seg_name = idc.get_segm_name(seg_ea)
    print(f"正在搜索代码段:{seg_name}")
 
    # 检查该段是否包含指令
    seg_type = idc.get_segm_attr(seg_ea, idc.SEGATTR_TYPE)
    if seg_type != idaapi.SEG_CODE:
        continue
 
    # 获取段的结束地址
    seg_end = idc.get_segm_end(seg_ea)
 
    for pattern in patterns:
        not_found = True  # 用于跟踪是否找到目标模式
 
        # 在该段内搜索
        ea = seg_ea
        while ea < seg_end:
            # 使用 ida_search.find_binary 搜索组合的指令模式
            ea = ida_search.find_binary(ea, seg_end, pattern, 16, idc.SEARCH_DOWN)
            if ea == idaapi.BADADDR:
                if not_found:
                    print(f"在代码段 {seg_name} 中未找到模式 {pattern}")
                break  # 未找到
 
            not_found = False  # 找到了目标模式
 
            # 检查是否已经是一个函数
            if idaapi.get_func(ea):
                print(f"地址 0x{ea:X} 已经是一个函数,跳过")
            else:
                # 如果找到匹配,尝试创建函数
                if not idaapi.add_func(ea):
                    print(f"在代码段 {seg_name} 的 0x{ea:X} 位置无法创建函数")
                else:
                    print(f"在代码段 {seg_name} 的 0x{ea:X} 位置成功创建函数")
 
            # 更新地址以继续搜索
            ea = idc.next_head(ea, seg_end)
 
print("脚本执行完毕")

来源: chatgpt

2023/9/3


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2023-10-14 08:39 被qux编辑 ,原因: "55 89 E5"也是函数开头
收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 203
活跃值: (1139)
能力值: ( LV9,RANK:195 )
在线值:
发帖
回帖
粉丝
2
chatgpt?能否分享一下如何利用chatgpt创建这一段代码的,这比这个代码更有意义
2023-9-12 16:34
0
雪    币: 13059
活跃值: (5723)
能力值: ( LV5,RANK:77 )
在线值:
发帖
回帖
粉丝
qux
3

## round1

### 问

ida python脚本 以"push ebp mov ebp, esp"开头的都创建函数


### 答

在 IDA Pro 中,你可以使用 Python 脚本来自动创建以 "push ebp; mov ebp, esp" 开头的函数。以下是一个简单的示例代码,演示如何做到这一点:


```python

import idautils

import idc

import idaapi


# 遍历所有的代码段

for seg_ea in idautils.Segments():

    # 获取段的结束地址

    seg_end = idc.get_segm_end(seg_ea)

   

    # 在该段内搜索

    ea = seg_ea

    while ea < seg_end:

        # 搜索 "push ebp" 指令

        ea = idc.find_binary(ea, seg_end, "55", 16, idc.SEARCH_DOWN)

        if ea == idaapi.BADADDR:

            break  # 未找到

       

        # 检查下一条指令是否为 "mov ebp, esp"

        next_ea = idc.next_head(ea, seg_end)

        next_mnem = idc.print_insn_mnem(next_ea)

        if next_mnem == "mov" and idc.get_operand_value(next_ea, 0) == 5 and idc.get_operand_value(next_ea, 1) == 4:

            # 如果找到匹配,尝试创建函数

            if not idaapi.add_func(ea):

                print("Failed to create function at 0x{:x}".format(ea))

            else:

                print("Function created at 0x{:x}".format(ea))

       

        # 更新地址以继续搜索

        ea = idc.next_head(ea, seg_end)

```


将这段代码复制粘贴到 IDA Pro 的 Python 控制台或者作为脚本运行。它会遍历所有代码段,寻找 "push ebp; mov ebp, esp" 指令序列,并尝试在这些位置创建函数。


注意:这个脚本是非常基础的,只用于演示。在实际应用中,你可能需要考虑更多的边缘情况和优化。



## round2

### 问

ida python脚本 在标记为instruction段的位置,搜索"push ebp mov ebp, esp",创建函数


### 答

在 IDA Pro 中,你可以使用 Python 脚本来在标记为指令(instruction)的段中搜索 "push ebp; mov ebp, esp" 并创建函数。以下是一个示例脚本:


```python

import idautils

import idc

import idaapi


# 遍历所有的代码段

for seg_ea in idautils.Segments():

    # 检查该段是否包含指令

    seg_type = idc.get_segm_attr(seg_ea, idc.SEGATTR_TYPE)

    if seg_type != idaapi.SEG_CODE:

        continue

   

    # 获取段的结束地址

    seg_end = idc.get_segm_end(seg_ea)

   

    # 在该段内搜索

    ea = seg_ea

    while ea < seg_end:

        # 搜索 "push ebp" 指令

        ea = idc.find_binary(ea, seg_end, "55", 16, idc.SEARCH_DOWN)

        if ea == idaapi.BADADDR:

            break  # 未找到

       

        # 检查下一条指令是否为 "mov ebp, esp"

        next_ea = idc.next_head(ea, seg_end)

        next_mnem = idc.print_insn_mnem(next_ea)

        if next_mnem == "mov" and idc.get_operand_value(next_ea, 0) == 5 and idc.get_operand_value(next_ea, 1) == 4:

            # 如果找到匹配,尝试创建函数

            if not idaapi.add_func(ea):

                print(f"无法在 0x{ea:X} 创建函数")

            else:

                print(f"已在 0x{ea:X} 创建函数")

       

        # 更新地址以继续搜索

        ea = idc.next_head(ea, seg_end)

```


这个脚本首先遍历所有段,并检查它们是否为代码段。然后,在每个代码段中搜索指令 "push ebp; mov ebp, esp"。找到后,它会尝试在该位置创建函数。


你可以将这段代码复制并粘贴到 IDA Pro 的 Python 控制台,或者保存为 `.py` 文件并在 IDA Pro 中运行该脚本。这将自动在找到的地址处创建函数。



## round3

### 问

"push ebp; "和"mov ebp, esp"合并在一起搜索


### 答

在 IDA Pro 的 Python 脚本中,你可以将 "push ebp" 和 "mov ebp, esp" 的机器码合并,然后一次性搜索它们。以下是如何实现这一点的示例代码:


```python

import idautils

import idc

import idaapi


# 合并 "push ebp" 和 "mov ebp, esp" 的机器码

# "push ebp" 的机器码是 55

# "mov ebp, esp" 的机器码是 89 E5

combined_pattern = "55 89 E5"


# 遍历所有的代码段

for seg_ea in idautils.Segments():

    # 检查该段是否包含指令

    seg_type = idc.get_segm_attr(seg_ea, idc.SEGATTR_TYPE)

    if seg_type != idaapi.SEG_CODE:

        continue

   

    # 获取段的结束地址

    seg_end = idc.get_segm_end(seg_ea)

   

    # 在该段内搜索

    ea = seg_ea

    while ea < seg_end:

        # 搜索组合的指令模式

        ea = idc.find_binary(ea, seg_end, combined_pattern, 16, idc.SEARCH_DOWN)

        if ea == idaapi.BADADDR:

            break  # 未找到


        # 如果找到匹配,尝试创建函数

        if not idaapi.add_func(ea):

            print(f"无法在 0x{ea:X} 创建函数")

        else:

            print(f"已在 0x{ea:X} 创建函数")

       

        # 更新地址以继续搜索

        ea = idc.next_head(ea, seg_end)

```


这个脚本将 "push ebp" 和 "mov ebp, esp" 的机器码合并为一个字符串 `combined_pattern`,然后在代码段中搜索这个组合模式。找到匹配项后,它会在该地址处尝试创建一个函数。


你可以将这段代码复制并粘贴到 IDA Pro 的 Python 控制台,或者保存为 `.py` 文件并在 IDA Pro 中运行该脚本。这将自动在找到的地址处创建函数。



## round4

### 问

"mov ebp, esp" 的机器码是 8B EC  


### 答

非常感谢您的更正。您是对的,"mov ebp, esp" 的机器码实际上是 "8B EC"。基于这个新信息,以下是更新后的代码:


```python

import idautils

import idc

import idaapi


# 合并 "push ebp" 和 "mov ebp, esp" 的机器码

# "push ebp" 的机器码是 55

# "mov ebp, esp" 的机器码是 8B EC

combined_pattern = "55 8B EC"


# 遍历所有的代码段

for seg_ea in idautils.Segments():

    # 获取段的名称

    seg_name = idc.get_segm_name(seg_ea)

    print(f"正在搜索代码段:{seg_name}")


    # 检查该段是否包含指令

    seg_type = idc.get_segm_attr(seg_ea, idc.SEGATTR_TYPE)

    if seg_type != idaapi.SEG_CODE:

        continue


    # 获取段的结束地址

    seg_end = idc.get_segm_end(seg_ea)


    # 在该段内搜索

    ea = seg_ea

    while ea < seg_end:

        # 搜索组合的指令模式

        ea = idc.find_binary(ea, seg_end, combined_pattern, 16, idc.SEARCH_DOWN)

        if ea == idaapi.BADADDR:

            break  # 未找到


        # 如果找到匹配,尝试创建函数

        if not idaapi.add_func(ea):

            print(f"在代码段 {seg_name} 的 0x{ea:X} 位置无法创建函数")

        else:

            print(f"在代码段 {seg_name} 的 0x{ea:X} 位置成功创建函数")


        # 更新地址以继续搜索

        ea = idc.next_head(ea, seg_end)

```


现在这个脚本应该能准确地搜索包含 "push ebp; mov ebp, esp" 的位置,并尝试在这些位置创建函数。再次感谢您的更正!



## round5

### 问

增加开始和结束提示


### 答

当然,为了更好地追踪脚本的进度,您可以在脚本开始和结束时添加提示信息。以下是包含这些提示的更新代码:


```python

import idautils

import idc

import idaapi


print("脚本开始执行")


# 合并 "push ebp" 和 "mov ebp, esp" 的机器码

# "push ebp" 的机器码是 55

# "mov ebp, esp" 的机器码是 8B EC

combined_pattern = "55 8B EC"


# 遍历所有的代码段

for seg_ea in idautils.Segments():

    # 获取段的名称

    seg_name = idc.get_segm_name(seg_ea)

    print(f"正在搜索代码段:{seg_name}")


    # 检查该段是否包含指令

    seg_type = idc.get_segm_attr(seg_ea, idc.SEGATTR_TYPE)

    if seg_type != idaapi.SEG_CODE:

        continue


    # 获取段的结束地址

    seg_end = idc.get_segm_end(seg_ea)


    # 在该段内搜索

    ea = seg_ea

    while ea < seg_end:

        # 搜索组合的指令模式

        ea = idc.find_binary(ea, seg_end, combined_pattern, 16, idc.SEARCH_DOWN)

        if ea == idaapi.BADADDR:

            break  # 未找到


        # 如果找到匹配,尝试创建函数

        if not idaapi.add_func(ea):

            print(f"在代码段 {seg_name} 的 0x{ea:X} 位置无法创建函数")

        else:

            print(f"在代码段 {seg_name} 的 0x{ea:X} 位置成功创建函数")


        # 更新地址以继续搜索

        ea = idc.next_head(ea, seg_end)


print("脚本执行完毕")

```


这个版本的脚本在开始时输出 "脚本开始执行",并在结束时输出 "脚本执行完毕"。这样,你就可以更清楚地了解脚本何时开始和结束了。



## round6

### 问

未找到时输出提示


### 答

当然,如果在某个代码段中未找到目标模式,输出一个相应的提示会很有用。以下是包含这个新功能的代码:


```python

import idautils

import idc

import idaapi


print("脚本开始执行")


# 合并 "push ebp" 和 "mov ebp, esp" 的机器码

# "push ebp" 的机器码是 55

# "mov ebp, esp" 的机器码是 8B EC

combined_pattern = "55 8B EC"


# 遍历所有的代码段

for seg_ea in idautils.Segments():

    # 获取段的名称

    seg_name = idc.get_segm_name(seg_ea)

    print(f"正在搜索代码段:{seg_name}")


    # 检查该段是否包含指令

    seg_type = idc.get_segm_attr(seg_ea, idc.SEGATTR_TYPE)

    if seg_type != idaapi.SEG_CODE:

        continue


    # 获取段的结束地址

    seg_end = idc.get_segm_end(seg_ea)


    not_found = True  # 用于跟踪是否找到目标模式


    # 在该段内搜索

    ea = seg_ea

    while ea < seg_end:

        # 搜索组合的指令模式

        ea = idc.find_binary(ea, seg_end, combined_pattern, 16, idc.SEARCH_DOWN)

        if ea == idaapi.BADADDR:

            if not_found:

                print(f"在代码段 {seg_name} 中未找到目标模式")

            break  # 未找到


        not_found = False  # 找到了目标模式


        # 如果找到匹配,尝试创建函数

        if not idaapi.add_func(ea):

            print(f"在代码段 {seg_name} 的 0x{ea:X} 位置无法创建函数")

        else:

            print(f"在代码段 {seg_name} 的 0x{ea:X} 位置成功创建函数")


        # 更新地址以继续搜索

        ea = idc.next_head(ea, seg_end)


print("脚本执行完毕")

```


这个版本的脚本在每个代码段的搜索结束时,如果没有找到目标模式,会输出 "在代码段 [段名] 中未找到目标模式"。这样,您就可以更清晰地了解脚本的搜索结果。



## round7

### 问

用ida_search.find_binary替换一下


### 答

确实,`ida_search.find_binary` 是 IDA 7.x 及更高版本中推荐用于搜索二进制数据的函数。以下是更新后的代码:


```python

import idautils

import idc

import idaapi

import ida_search


print("脚本开始执行")


# 合并 "push ebp" 和 "mov ebp, esp" 的机器码

# "push ebp" 的机器码是 55

# "mov ebp, esp" 的机器码是 8B EC

combined_pattern = "55 8B EC"


# 遍历所有的代码段

for seg_ea in idautils.Segments():

    # 获取段的名称

    seg_name = idc.get_segm_name(seg_ea)

    print(f"正在搜索代码段:{seg_name}")


    # 检查该段是否包含指令

    seg_type = idc.get_segm_attr(seg_ea, idc.SEGATTR_TYPE)

    if seg_type != idaapi.SEG_CODE:

        continue


    # 获取段的结束地址

    seg_end = idc.get_segm_end(seg_ea)


    not_found = True  # 用于跟踪是否找到目标模式


    # 在该段内搜索

    ea = seg_ea

    while ea < seg_end:

        # 使用 ida_search.find_binary 搜索组合的指令模式

        ea = ida_search.find_binary(ea, seg_end, combined_pattern, 16, idc.SEARCH_DOWN)

        if ea == idaapi.BADADDR:

            if not_found:

                print(f"在代码段 {seg_name} 中未找到目标模式")

            break  # 未找到


        not_found = False  # 找到了目标模式


        # 如果找到匹配,尝试创建函数

        if not idaapi.add_func(ea):

            print(f"在代码段 {seg_name} 的 0x{ea:X} 位置无法创建函数")

        else:

            print(f"在代码段 {seg_name} 的 0x{ea:X} 位置成功创建函数")


        # 更新地址以继续搜索

        ea = idc.next_head(ea, seg_end)


print("脚本执行完毕")

```


这个版本使用了 `ida_search.find_binary` 函数,其他部分保持不变。如果您正在使用 IDA 7.x 或更高版本,这个版本应该更加合适。



## round8

### 问

如果已经创建了函数,就不要再创建函数


### 答

如果你想避免重复创建函数,你可以在尝试创建函数之前检查该地址是否已经是一个函数的起始地址。这可以通过 `idaapi.get_func` 函数实现,该函数会返回一个 `func_t` 对象,如果给定地址是一个函数的一部分的话。


下面是修改后的代码:


```python

import idautils

import idc

import idaapi

import ida_search


print("脚本开始执行")


# 合并 "push ebp" 和 "mov ebp, esp" 的机器码

# "push ebp" 的机器码是 55

# "mov ebp, esp" 的机器码是 8B EC

combined_pattern = "55 8B EC"


# 遍历所有的代码段

for seg_ea in idautils.Segments():

    # 获取段的名称

    seg_name = idc.get_segm_name(seg_ea)

    print(f"正在搜索代码段:{seg_name}")


    # 检查该段是否包含指令

    seg_type = idc.get_segm_attr(seg_ea, idc.SEGATTR_TYPE)

    if seg_type != idaapi.SEG_CODE:

        continue


    # 获取段的结束地址

    seg_end = idc.get_segm_end(seg_ea)


    not_found = True  # 用于跟踪是否找到目标模式


    # 在该段内搜索

    ea = seg_ea

    while ea < seg_end:

        # 使用 ida_search.find_binary 搜索组合的指令模式

        ea = ida_search.find_binary(ea, seg_end, combined_pattern, 16, idc.SEARCH_DOWN)

        if ea == idaapi.BADADDR:

            if not_found:

                print(f"在代码段 {seg_name} 中未找到目标模式")

            break  # 未找到


        not_found = False  # 找到了目标模式


        # 检查是否已经是一个函数

        if idaapi.get_func(ea):

            print(f"地址 0x{ea:X} 已经是一个函数,跳过")

        else:

            # 如果找到匹配,尝试创建函数

            if not idaapi.add_func(ea):

                print(f"在代码段 {seg_name} 的 0x{ea:X} 位置无法创建函数")

            else:

                print(f"在代码段 {seg_name} 的 0x{ea:X} 位置成功创建函数")


        # 更新地址以继续搜索

        ea = idc.next_head(ea, seg_end)


print("脚本执行完毕")

```


这个版本在尝试创建函数之前会检查是否已经有一个函数存在于该地址。如果已经存在,脚本将输出一个消息并跳过该地址。这样,你就不会重复创建函数了。



2023-9-13 07:30
0
雪    币: 3070
活跃值: (30876)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
感谢分享
2023-9-13 09:20
1
游客
登录 | 注册 方可回帖
返回
//