sus 逆向 writrup

本文记录了作者在东南平台进行逆向工程的解题过程,涵盖了从简单的helloworld到复杂的边信道攻击等不同难度的题目。通过分析汇编、使用工具如ida和z3,以及爆破和符号执行等方法,解密了各题目的关键算法,包括字符串解密、斐波那契递归、CRC校验等,并分享了解题思路。
摘要由CSDN通过智能技术生成
  • 东南的平台又放了新题,这次决定都做一下试试,在这里记录解题过程,因为是平时练习,我会尽可能多的把思路和解法写全,鉴于东南平台的wp不是很多,也方便下一届萌新的自主练习.平台地址:http://sus.njnet6.edu.cn

helloworld

  • 逆向签到题,直接f5看到内部if条件即可
  • 抛开f5,分析一下汇编,首先是函数头部连续mov到栈中的数据,也就是flagenc
1
2
3
4
5
6
7
mov     dword ptr [ebp+flag], 0C881E8F1h
mov     dword ptr [ebp+flag+4], 0CECF81D2h
mov     dword ptr [ebp+flag+8], 81C081D5h
mov     dword ptr [ebp+flag+0Ch], 0C8D5C0D3h
mov     dword ptr [ebp+flag+10h], 0CDC0CFCEh
mov     dword ptr [ebp+flag+14h], 0CCD4CF81h
mov     dword ptr [ebp+flag+18h], 8FD3C4C3h
  • 之后程序%d读入数字,随后cmp比较
1
2
3
4
add     esp, 10h
mov     eax, [ebp+n]
cmp     eax, 12B9B0A1h
jnz     short loc_804852D
  • 随后进入字符串解密的过程,lea将偏移地址给了edx,然后吧eax偏移取了以后,将*eax的值给到eax,如果eax不为0,那么进入一个汇编块中
1
2
3
4
5
6
7
8
9
10
11
12
lea     edx, [ebp+flag]
mov     eax, [ebp+i]
add     eax, edx
movzx   edx, byte ptr [eax]
mov     eax, [ebp+n]
mov     ecx, edx
xor     ecx, eax
lea     edx, [ebp+flag]
mov     eax, [ebp+i]
add     eax, edx
mov     [eax], cl
add     [ebp+i], 1
  • 我们可以看出来,首先按照i获取偏移,然后将值传给edx,接着是将刚才输入的n的值的一byte传给eax,随后进行一个异或然后从新把值赋会到flag[i],然后进行i++.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from struct import pack
def p32(i):
    return pack("<I", i)

a = [0xC881E8F1,
0xCECF81D2,
0x81C081D5,
0xC8D5C0D3,
0xCDC0CFCE,
0xCCD4CF81,
0x8FD3C4C3]

t = ""

for i in a:
    t += p32(i)

flag = ""

for i in range(len(t)):
    flag += chr(ord(t[i])^0xa1)

print flag

simple-rev

  • 先说正常做法:ida定位main函数,f5,发现读入后进行一个循环遍历,非空或者回车的,每位加上1,最后一个字符串比较,逆向过程即为每位字符串减一
  • 汇编的话,函数头fgets读入z字符串,给栈空间的i赋值为0,将数组的首地址给到edx后继续取偏移,值为为0时跳出到strcmp所在代码块中,否则进入一个循环
  • 循环内还有两个判断,一个是为0xa跳到的循环,一个是非0xa的循环,内部汇编比较清晰,获取偏移随后add加一
1
2
3
4
5
a = [ord(i) - 1 for i in "UIJT.JT.ZPVS.GMBH"]
flag = ""
for i in a:
    flag += chr(i)
print flag

bitx

  • 很像asi3的题,简直是一样的,没有那个题复杂,但是主要算法就是一行
  • 另一个题目经常被拿来用于做符号执行的讲解,这里说一下符号执行,因为命令行符号执行默认参数范围的问题,会从0开始输入,然而这样会截断我们的输入,所以我们要加上一些限制,脚本如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import angr
import claripy

p = angr.Project("./bitx",auto_load_libs=False)
arg1 = claripy.BVS('arg1', 50*8)
args = [p.filename,arg1]
s = p.factory.entry_state(args=args)

for byte in arg1.chop(8):
    s.add_constraints(byte != '\x00') 
    s.add_constraints(byte >= ' ') 
    s.add_constraints(byte <= '~') 

simgr = p.factory.simgr(s)
simgr.explore(find = 0x8048508,avoid = 0x804851A)

print simgr.found[0].solver.eval(args[1], cast_to=str)

mozhucy@ubuntu:~/Desktop/mac/Home/Desktop$ python 1.py
WARNING | 2018-09-08 18:17:26,007 | angr.analyses.disassembly_utils | Your version of capstone does not support MIPS instruction groups.
FLAG{Swap two bits is easy 0xaa with 0x55} @

unpackme

  • 这个题居然到了400分..题目名字是unpackme,众所周知,CTF中对于逆向的考察中,壳的考察是比较少的,这个题目名很明显是加了壳,查壳发现居然不是自写壳,而是upx壳,直接上脱壳机,脱壳后进行算法逆向,定位到关键算法,可以看到函数先对输入进行hash运算,然后进行hash的一个循环比较,我们可以提取出这些hash,发现正好为32位,somd5反查一下,发现解密后的字符串是”how[空格]do[空格]you[空格]turn[空格]this”,很神奇,随后是函数的解密过程,经过化简后可以得到算法 flag[i] = flag[0] ^ md5flag[i/2] ^ key[i],其中已知两个参数,这里选择爆破flag的第一字节,脚本如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import string
import binascii

flag = ""
flagenc = [0x1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值