用angr解决一个函数

逆向工程 愤怒
2021-07-05 09:30:03

看看这个c程序:

#include <stdio.h>

int my_function(int a, int b);

int my_function(int a, int b)
{
    // Imagine a very complex calculation on 'a' and 'b'
    if (a==0x41 && b==0x42)
    {
        return 1;
    }
    return 0;
}


int main(int argc , char *argv[])
{
    int c = 10;
    int d = 10;
    // Lot of stuff, including UI
    if (my_function(c,d)==1)
    {
        printf("Good\n");
    }
    else
    {
        printf("Wrong !\n");
    }
    return 0;
}

假设我已经编译了这个程序并且我没有源代码。

这是使用反汇编器看到的内容:

...
0x00001180      e8b0ffffff     call sym.my_function
....

|           ; var int local_8h @ rbp-0x8
|           ; var int local_4h @ rbp-0x4
|           ; CALL XREF from 0x00001180 (main)
|           0x00001135      55             push rbp
|           0x00001136      4889e5         mov rbp, rsp
|           0x00001139      897dfc         mov dword [local_4h], edi
|           0x0000113c      8975f8         mov dword [local_8h], esi
|           0x0000113f      837dfc41       cmp dword [local_4h], 0x41  ; [0x41:4]=0x4000000 ; 'A'
|       ,=< 0x00001143      750d           jne 0x1152
|       |   0x00001145      837df842       cmp dword [local_8h], 0x42  ; [0x42:4]=0x40000 ; 'B'
|      ,==< 0x00001149      7507           jne 0x1152
|      ||   0x0000114b      b801000000     mov eax, 1
|     ,===< 0x00001150      eb05           jmp 0x1157
|     |||   ; JMP XREF from 0x00001143 (sym.my_function)
|     |||   ; JMP XREF from 0x00001149 (sym.my_function)
|     |``-> 0x00001152      b800000000     mov eax, 0
|     |     ; JMP XREF from 0x00001150 (sym.my_function)
|     `---> 0x00001157      5d             pop rbp
\           0x00001158      c3             ret

我想要做的是编写一个 python/angr 程序,它会尝试解决这个函数,并告诉我应该向函数发送哪个参数以返回 1。

换句话说,我想问angr这个问题:

“从 0x00001135 地址开始分析。告诉我我应该在 rbp-0x8 和 rbp-0x4 内存地址中放入什么才能达到 0x0000114b 代码”。

谢谢

* 用字符串编辑 *

#include <stdio.h>
#include <string.h>

int my_function(char *s);

int my_function(char *s)
{
        if (strlen(s)!=4)
        {
                return 0;
        }

        for (int i=0;i<4;i++)
        {
                s[i]++;
        }

        if (strncmp(s,"b{fs",4)==0)
        {
                return 1;
        }
        return 0;
}


int main(int argc , char *argv[])
{
        if (my_function(argv[1])==1)
        {
                printf("Good\n");
        }
        else
        {
                printf("Wrong !\n");
        }
        return 0;
}
1个回答

感谢您的示例场景。

作为免责声明,我用 clang 编译了您的示例源代码,我的反汇编如下所示:

拆卸

那么你所需要的只是一个像这样的小 python 脚本:

import angr

function_start = 0x4004f0
function_target = 0x40050e
function_end = 0x400521

p = angr.Project("./a.out")
state = p.factory.blank_state(addr=function_start)
a = state.solver.BVS('a', 32)
b = state.solver.BVS('b', 32)
state.regs.esi = b
state.regs.edi = a

sm = p.factory.simulation_manager(state)
sm.explore(find=function_target, avoid=function_end)

found_path = sm.found[0]
print 'a: %d\nb: %d' % (found_path.state.se.eval(a), found_path.state.se.eval(b))

请注意这个例子是微不足道的,但在任何其他情况下,您应该尝试添加尽可能多的值约束。

编辑

在这里,我们再次使用堆栈变量条件。为此,我们只跳过函数的前 4 条指令:

import angr

function_start = 0x4004fa
function_target = 0x40050e
function_end = 0x400521

p = angr.Project("./a.out")
state = p.factory.blank_state(addr=function_start)
a = state.solver.BVS('a', 32)
b = state.solver.BVS('b', 32)
state.mem[state.regs.rbp - 0x8].uint32_t = a
state.mem[state.regs.rbp - 0xc].uint32_t = b

sm = p.factory.simulation_manager(state)
sm.explore(find=function_target, avoid=function_end)

found_path = sm.found[0]
print 'a: %d\nb: %d' % (found_path.state.se.eval(a), found_path.state.se.eval(b))