Trying to run a buffer-overflow with Python/pwntools

1.6k views Asked by At

I work on a online program in which I should do a buffer Overflow.
When I run the program, I have to complete a sum of two numbers generated randomly) :

>>> 451389913 + 1587598959 =

If I put the right result, I get a "That's okay". Otherwise the console writes "Try it again".

I decompiled the program with Ghidra and get the following code in the main() function :

{
  int iVar1;
  char local_9 [36];
  int local_42;
  uint local_6;
  uint local_f;
  
  local_f = rand();
  local_6 = rand();
  local_42 = local_6 + local_f;
  printf(">>> %d + %d = ",(ulong)local_f,(ulong)local_6);
  fflush(stdout);
  fgets(local_9,100,stdin);
  iVar1 = atoi(local_9);
  if (local_42 == iVar1) {
    puts("That's ok");
  }
  else {
    puts("Try it again");
  }
  return 0;
}

I notice a fgets function that make me suppose I can do the buffer overflow just before the sum. I also see that the local9 variable is composed of 36 characters. So I suppose that at the beginning of the payload, there must be 36 characters.

I began to write the following snippet with the pwntools Python library :

import pwn
offset = 36
payload = b'A'*offset + b'[.....]'
c = pwn.remote("URL",Port)
c.sendline(payload)
c.interactive()

The thing is I know I have to write something after the b'A'*offset but I don't really see what to add.. My difficulty is to join that sum of random numbers to the payload.
Is it possible to do it ?

Any ideas would be very appreciated, thanks

1

There are 1 answers

0
xicc On

Of course, it's possible, pwn is the swiss army knife for CTFs.

# string = c.recv()
# assuming the string you receive is this
string = b">>> 451389913 + 1587598959 ="

# receive expression as bytes
# convert it into utf8 string for convenience
# split() splits the string at whitespaces and store them as array elements
expression = string.decode("utf8").split()

# covert string to int for to get logical sum instead of literal
solution = int(expression[1])+int(expression[3])
c.sendline(payload)

However, in a more challenging scene, where the server might ask you multiple answers with division or difference you'd have to change operators as needed. And I'd rather use operator lib than write a bunch of ifs.

import operator

ops = {
    '+' : operator.add,
    '-' : operator.sub,
    '*' : operator.mul,
    '/' : operator.truediv
}

string = b">>> 451389913 + 1587598959 ="
expression = string.decode("utf8").split()

solution = ops[expression[2]](int(expression[1]), int(expression[3]))
c.sendline(solution)