1

Look at this c program:

#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;
}

Suppose i have compiled this program and i do not have source code.

Here is what is see with a disassembler:

...
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

What i want to do is to write a python/angr program which will try to solve this function and tell me which argument i should send to the function in order to return 1.

In other words, i want to ask angr this question:

"Start your analyse at 0x00001135 address. Tell me what i should put in rbp-0x8 and rbp-0x4 memory addresses in order to reach 0x0000114b code".

Thanks

* EDIT WITH STRING *

#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;
}

closed as too broad by perror, Nordwald, 0xC0000022L Feb 1 at 12:53

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    You seem to be familiar enough with RE.SE to know we provide assistance, not complete solutions without previous attempts. What have you tried doing and why didn't that work? – NirIzr Jan 29 at 9:41
  • Currently, this is too broad. Please provide details, such as the code for the function you want to analyze – julian Jan 29 at 22:44
  • okay see my edit – Bob5421 Jan 30 at 6:58
4

thanks for your example scenario.

As a disclamer, I compiled your example source code with clang and my disassembly looks like this:

disassembly

Then all you need is a small python script like this:

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))

Please note this example is trivial, but in any other case you should try to add as many constraints on values as possible.

edit

Here we go again with stack variable conditions. For this sake, we just skip the first 4 instructions of the function:

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))
  • thanks for your answer. Which tool provides your screenshot ? how should i do if i want to solve from memory addresses (relative to esp/ebp or not) instead of registers ? Thanks – Bob5421 Jan 30 at 8:10
  • @Bob5421 The screenshot was taken from binaryninja, but there are plenty of tools which do this (IDA free 7.0, radare for example). I'll edit my answer with another solution for the stack variables – Nordwald Jan 30 at 8:18
  • Okay thanks i have forgotten to ask you something. What should i do if the variables are not int but buffer (strings) – Bob5421 Jan 30 at 8:42
  • @Bob5421 It does not change a lot. You can pass cast_to=str to an eval call to get an actual string. If you have any problem with it, feel free to ask ;) – Nordwald Jan 30 at 8:48
  • I have tried: "state.mem[state.regs.rbp - 0xc].string=state.solver.BVS('a', 8*15)" and i get this error: "AttributeError: 'SimTypeString' object has no attribute 'store'" – Bob5421 Jan 30 at 9:49

Not the answer you're looking for? Browse other questions tagged or ask your own question.