Giter VIP home page Giter VIP logo

ustc-hackergame / hackergame2020-writeups Goto Github PK

View Code? Open in Web Editor NEW
470.0 470.0 67.0 31.39 MB

Hackergame 2020 的官方与非官方题解

License: Other

Dockerfile 0.06% Python 1.78% Makefile 0.02% C 39.26% C++ 47.77% HTML 0.42% CSS 0.61% JavaScript 8.06% Shell 0.02% Go 0.37% Haskell 0.23% Java 0.13% CMake 0.22% Objective-C 0.12% GLSL 0.01% Sage 0.03% Assembly 0.01% Kotlin 0.61% SCSS 0.26%

hackergame2020-writeups's People

Contributors

arm64v8a avatar emc2314 avatar gztimewalker avatar harukama avatar hykilpikonna avatar hzqmwne avatar imlonghao avatar itxcjm avatar konano avatar ksqsf avatar lawvs avatar libreliu avatar lyciumlee avatar metlee avatar mlzeng avatar naivetomcat avatar proffan avatar ranwen avatar renbaoshuo avatar rubyocelot avatar sparkcyf avatar stefan0us avatar taoky avatar tounan avatar ustc-zzzz avatar volltin avatar waterking201030 avatar wegfan avatar yssickjgd avatar zzh1996 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hackergame2020-writeups's Issues

自复读的复读机-栈帧解法

看到题目一开始的想法是试着去找 input 读入变量的值。
但是把源码拖下来一看,exec(input())这没法玩啊

这行代码的字节码:

  1           0 LOAD_NAME                0 (exec)
              2 LOAD_NAME                1 (input)
              4 CALL_FUNCTION            0
              6 CALL_FUNCTION            1
              8 RETURN_VALUE

Python 内部完全没提供访问这个 input 输入临时字符串的功能。

str 类型不受 gc 跟踪,代表 gc.get_objects() 没法用,又因为这是个中间变量,也不存在于 globals,locals 里,代码对象也和这玩意没关系。

本来想着试试 ctypes 到处摸一摸,但在写的时候发现在 exec 中有更方便的解法。

exec 本身就是一个确定的代码对象,可以从栈帧上找到这个代码对象和它的常量等信息,稍微好做一点。

inner_code = b'''import inspect
import hashlib
d=inspect.currentframe().f_back.f_code.co_consts[0]
inp=f"exec(bytes.fromhex('{d}').decode())"
print(hashlib.sha256(inp.encode()).hexdigest(),end='')
'''.hex()

print(f'exec(bytes.fromhex(\'{inner_code}\').decode())')

(从大佬那学到了从mem里翻出输入字符串 大佬tql

从零开始记账工具人

无脑做法: numpy 把 0~100 分成 10000 份(分割函数参数要写10001),交给cn2an 进行转换,凑成字典,翻转字典,对Excel 第一列进行查找乘个数加和,不在范围内只有一个,手动加上得到结果

中间人timing-attack padding oracle exp

我没找到有人写这题非预期解的实现,故按题解中的描述实现了一份(还挺快的):

from pwn import *
from hashlib import sha256
from utils import *
import time

is_remote = True if 1 == 1 else False # chang this for switch remote/local

if is_remote:
    r = remote('202.38.93.111', 10041)
    r.sendlineafter('token:', 'xxx:yyy') # your token
else:
    r = process(['python3', './entry.py'])

r.sendlineafter('to play (1/2/3)? ', '3') # chang this for switch task2/3

def enc(prefix, suffix):
    r.sendlineafter('talk to? ', 'Alice')
    r.sendlineafter('s your name? ', bytes(prefix).hex())
    r.sendlineafter(' else do you want to say? ', bytes(suffix).hex())
    c = r.recvuntil('Whom do')
    return bytes.fromhex(c.split(b'please take it to Bob:\n')[1].split(b'\nWhom do')[0].decode())

prelen = len(b"Thanks " + b" for taking my flag: ")

def calc_len():
    global prelen
    st = len(enc(b'',b''))
    app = 0
    while True:
        app += 1
        if len(enc(b'a' * app,b'')) != st:
            break
    return st - app - prelen - 16 - len(hmac_crc128(b'x' * 16,b'y' * 16))

def oracle_test(data):
    r.sendlineafter('talk to? ', 'Bob')
    r.sendlineafter('essage from Alice: ', bytes(data).hex())
    t = time.time()
    c = r.recvuntil('Whom do')
    t = time.time() - t
    return t

def original_oracle(data):
    r.sendlineafter('talk to? ', 'Bob')
    r.sendlineafter('essage from Alice: ', bytes(data).hex())
    t = time.time()
    c = r.recvuntil('Whom do')
    t = time.time() - t
    if t < theta:
        return False
    return True

test_cnt = 5

def oracle(data):
    global test_cnt
    t_cnt = 0; f_cnt = 0
    for i in range(test_cnt):
        if original_oracle(data):
            t_cnt += 1
        else:
            f_cnt += 1
        if (t_cnt == 0 and f_cnt >= 2) or (f_cnt == 0 and t_cnt >= 2):
            break
        if t_cnt > test_cnt // 2 or f_cnt > test_cnt // 2:
            break
    return True if t_cnt > f_cnt else False

alphabet = b'qwertyuiopasdfghjklzxcvbnm' # more possible char in flag (for speed up)
morePoss = b'0123456789_' + alphabet + alphabet.upper() + b'{}\n'

def padding_attack(chiper, required, known = b''):
    for i in range(len(chiper), len(chiper) - required, -1):
        if i + len(known) > len(chiper):
            continue
        cons = (len(chiper) - i) % 16
        val = cons + 1
        cur = None
        in_chiper = chiper[i - 17]
        pre = chiper[: i - 17]
        suffix = bytes([known[j] ^ chiper[i - 16 + j] ^ val for j in range(cons)])
        suffix += chiper[i - 16 + cons : len(chiper) - (len(chiper) - i) // 16 * 16]
        poss = []
        for j in morePoss:
            poss.append(j ^ val ^ in_chiper)
        for j in range(256):
            if j not in poss:
                poss.append(j)
        for j in poss:
            if oracle(pre + bytes([j]) + suffix):
                cur = j ^ val ^ in_chiper
                if val == 1:
                    if j != in_chiper:
                        break
                else:
                    break
        if cur == None:
            print('failed')
            quit()
        else:
            known = bytes([cur]) + known
            #if len(chiper) == i:
            #    known = known * known[0] # is padding
            print(known)
            

flag_len = calc_len()
rubbish_len = 3000 # change this when the network is slow
rubbish_len = rubbish_len + 16 - (rubbish_len + prelen + flag_len) % 16

wanted_cnt = flag_len
known = b''

good = enc(b'*'*rubbish_len, b'')
t1 = oracle_test(good)
bad = good[:-1] + bytes([good[-1] ^ 1])
t2 = oracle_test(bad)

goods = enc(b'*'*(rubbish_len - wanted_cnt), b'')
t1s = oracle_test(goods)
bads = goods[:-1] + bytes([goods[-1] ^ 1])
t2s = oracle_test(bads)

print('good time = ', t1s, '~', t1)
print('bad time = ', t2s, '~', t2)
if t1s < t2:
    print('waring: bad oracle!')
theta = (t1s + t2) / 2
print('suggest theta = ', theta)
padding_attack(enc(b'*'*rubbish_len, b'')[:-32], wanted_cnt, known)

签到题

可以先把滑标拖到0,点击提交后上方的网址会出现balabal/number=0,将其改为number=1,就可以得到flag
qwq

Flag 计算机官方题解中的问题

看一直没修,还是开个 issue 提一下。

官方题解中提到 IDA 识别字符串:

逆向的核心过程就是明白程序干了哪些事情,橙色的操作数代表着地址,我们将鼠标悬停在上面,然后右键把它类型转换一下。
[图片]
IDA 就能识别字符串了。

但在此题上下文甚至提供的截图中,这个做法是有问题的:由于段寄存器指向的内存位置不同,IDA 无法一直正确识别一个数字具体引用的位置;此题中 DS 和 SS 的差值就会导致直接在 IDA 中转换内存引用会产生不正确的结果。(甚至截图里直接引用的是一个“字符串+20h“,显然是不正确的。)

我的题解里描述了至少是本题上下文中的具体原理。

超安全的代理服务器

关于超安全的代理服务器这题,提出获取Secret的Method3
可以用chrome://net-internals/#http2
新版的chrome把此功能改到了chrome://net-export/,通过log文件读到
{"params":{"headers":[":method: GET",":scheme: https",":authority: 146.56.228.227",":path: /62d9b249-d6d8-4714-8ea0-9f3b413d5165"],"id":85,"promised_stream_id":54},"phase":0,"source":{"id":76608,"start_time":"319510568","type":9},"time":"320091658","type":206},

关于“室友的加密硬盘”官方题解中提到的非预期解

不知是因为 LUKS 分区打开的时候本该如此,还是出题人操作不慎在分区创建的时候密码复制到了剪贴板上,密码本身明文在 swap 中出现了,所以 strings 一下然后逐个字符串尝试就可以求解。但感觉其实这样做出来也算是正常解法了。密码是什么留作练习。

一时兴起想试着通过这种方式解一下,首先将 swap 分区单独拿出来:

dd if=roommates_disk_part.img of=swap.img bs=512 count=1497088 skip=393216  

然后用 GCC binutils 中的 strings 工具将文件中的字符串提取出来:

strings swap.img > swap.strings

一眼看过去挺多重复的,用 uniq 去一下重:

sort swap.strings | uniq > swap.strings.uniq

这样就得到了一个词典,使用 Hashcat 的 LUKS 模式破解:

hashcat -a 0 -m 14600 chome.img swap.strings.uniq -o hashcat-recovered2 --force

在旧机子上跑了一整天,破解出来了一个密码(Recovered...1/2,因为事先按照官方题解添加了一个密码 1 所以显示有两个)

[s]tatus [p]ause [b]ypass [c]heckpoint [q]uit => s

Session..........: hashcat
Status...........: Running
Hash.Name........: LUKS
Hash.Target......: chome.img
Time.Started.....: Mon Feb  1 16:43:05 2021, (1 day, 2 hours)
Time.Estimated...: Wed Feb  3 07:46:31 2021, (12 hours, 27 mins)
Guess.Base.......: File (swap.strings.uniq)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:       11 H/s (6.58ms) @ Accel:4 Loops:128 Thr:8 Vec:1
Recovered........: 1/2 (50.00%) Digests, 1/2 (50.00%) Salts
Progress.........: 1140480/2129440 (53.56%)
Rejected.........: 0/1140480 (0.00%)
Restore.Point....: 569856/1064720 (53.52%)
Restore.Sub.#1...: Salt:1 Amplifier:0-1 Iteration:503296-503424
Candidates.#1....: K-|g.} ->         ki
$ cat hashcat-recovered
chome.img:h189-~asfnb.asdfjp2i3

看起来 h189-~asfnb.asdfjp2i3 就是密码了,试着用这个密码解密分区,成功。

$ dd if=roommates_disk_part.img of=chome.img bs=512 count=1998848 skip=1892352
$ sudo cryptsetup luksOpen chome.img chome                              
Enter passphrase for chome.img: h189-~asfnb.asdfjp2i3
$ sudo mount /dev/mapper/chome /mnt       
$ cat /mnt/petergu/flag.txt 
flag{lets_do_A_c01d_b00t_next_time}

一些细节:虽然我的机子是 i915 集成显卡,但用使用了 GPU 计算的 Hashcat 仍然比使用多线程 CPU 运算的 bruceforce-luks 要快 20 倍左右。

2048硬玩通关:

打开题目时游戏不会刷新(重新开始),所以在没玩死时可以一次性打开多个界面,当成存档,如果一个界面游戏玩死了,就打开另一个重新玩,玩到足够高的分数时,再打开多个游戏界面,当存档用。

crc128生成多项式怎么计算得到的?

常见的crc32,crc16的生成多项式都是约定好的,不过这次中间人攻击的那道题里面有一个crc128,针对这种位数较多,且不常见的crc(如crc128,crc256等),他们的生成多项式是如何生成的呢?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.