week1
第一周……题很简单,写得比较乱,就这样吧…………
1 | In [1]: x = [0x5b,0x54,0x52,0x5e,0x56,0x48,0x44,0x56,0x5f,0x50,0x3,0x5e,0x56,0x6c,0x47,0x3,0x6c,0x41,0x56,0x6c,0x44,0x5 |
1 | box = [8, 6, 7, 6, 1, 6, 0xD, 6, 5, 6, 0xB, 7, 5, 6, 0xE, 6, |
本来以为是出题人的恶趣味,结果只是不小心出错了emmmm
1 |
|
1 |
|
1 | #在 http://factordb.com/ 分解n |
1 | import binascii |
week2
before main
init函数换了base64的码表
1 | import base64 |
math
矩阵相乘,用输入矩阵乘以box1,得到box2,最终用box2乘以box1的逆矩阵即可还原输入矩阵。
1 | box1 = matrix([[126,225,62,40,216],[253,20,124,232,122],[62,23,100,161,36],[118,21,184,26,142],[59,31,186,82,79]]) |
stream
md。。。这题做得我想鼠。。。
解包之后反编译,明显RC4+base64
但是直接写脚本是解不出来的……
这是为什么呢?哦~原来是encode的锅,只要把base解密之后的密文再decode回去就好了~……
1 | import base64 |
最后一个安卓xtea,不写了,摆了。
week3
kunmusic
C#写的,直接看DLL,用dnspy
main函数里有:
1 | private static void Main() |
直接调试断到这里,自己把数据拖出来异或。数据太长就不放脚本了。
得到一个exe文件,还是C#写的,dnspy里看一个叫music的类:
1 | public void music(object sender, EventArgs e) |
z3解方程+异或,不过这个题有多解,需要自己根据flag看着限制一下z3的解 这一步真的好折磨……
1 | from z3 import * |
最终异或得flag
1 | num = [0]*13 |
patchme
好折磨。。。最开始搜到系统调用就直接开始改,用的int 0x80,后来才发现那是32位的系统调用,64位要用syscall…… 对不起我是傻子
然后参数长度刚开始看的栈上是0x20(别问我咋看的,我也不知道),后来输入输出都没问题,确信是参数长度有问题,才看IDA的伪代码长度是24……
漏洞存在于主函数:
1 | __int64 __fastcall sub_13E8(int a1, __int64 a2) |
gets读取的输入长度无限制,可以通过gets布置payload以达到控制程序流程的目的,而printf存在格式化字符串漏洞。所以这里主要修复这两个函数。
可以将gets改为系统调用sys_read,printf改成系统调用sys_write,系统调用参数查询系统调用约定
把
1 | .text:000000000000141F lea rax, [rbp-20h] |
改成
1 | .text:000000000000141F lea rsi, [rbp-20h] ; buf |
(我为了省地方,清零都用的xor)
保存运行,随便输点啥即可hgame{You_4re_a_p@tch_master_0r_reverse_ma5ter}
cpp
究极折磨的题……调N年看不懂在干什么,后来发现应该是单字节加密,遂爆破
由于本人菜得不会hook库函数,遂决定patch输出爆破。具体而言就是把输出字符串patch成加密后的密文,和程序里原有的密文对比,对比正确的长度多一位则说明这一位正确。密文很好找,在sub_140003080。
关于具体怎么patch,先去找memcmp函数,也就是最终密文和输入加密后的密文对比的地方,固定基址之后在sub_140007D70。去看这个函数的汇编,调用memcmp前,我们需要的指针在rdx里,那么想办法保留rdx的值,我选择把它暂存在r15里,等到最后调用输出的时候直接用r15覆盖rdx即可。
具体而言就是改成下面这样:
1 | .text:0000000140007D9C 48 89 C2 mov rdx, rax |
写交互脚本爆破:
1 | import subprocess |
week4
好像很麻烦,经典go+vm,懒得写了,就这样吧……
关于本文
本文作者 云之君, 许可由 CC BY-NC 4.0.