2022 TCTF / RisingstarCTF reverse题 vintage 两关的Writeup

使用的工具

一开始用了ParaJVE 这个模拟器, 然后发现他没有调试功能, 因此放弃

f9dasm : 用于反汇编(后来看别人的wp发现ghidra对于这个架构支持反编译到伪代码的功能,会比直接看汇编方便很多)

vectrexy : 另一款模拟器,带有简单的调试功能

CheatEngine: 破解游戏可少不了它(下文用CE简称)

6809指令集 : 对着看指令集进行逆向

part 1

比赛一开始放出来的题里它是唯一一道500分的, 柿子要挑软的捏, 于是就入了这个坑.

一开始找了ParaJVE模拟器,因为是简单题,猜猜就是一个xor加密比较什么的。所以就直接打开CE,随便输入一点字符,然后搜索了一下我们输入的字符。多试了试很快发现我们的输入被异或了! #"%$'& , 做到这里我以为就是一个xor,觉得已经稳了,于是我dump下来整个内存直接循环异或! #"%$'& ,然后发现没有解。在CE上下硬件断点跟踪也发现不出什么有意义的代码,于是卡了一会。

之后队友发现了vectrexy这款带调试功能的模拟器, 于是我才意识到原来这个游戏的架构并非x86(难怪我说CE下硬件断点怎么会跟不到东西), 因此才去查资料得知游戏用的是6809指令集。于是我找了一个6809的反汇编器f9dasm反汇编了game.bin文件。 找到工具以后题目就很简单了, 在异或后的位置下个硬件断点,然后看一下断住部分附近的汇编代码(Z1BA7),发现还有一个异或,然后后面就跟着最后的比较代码(Z1BEF),dump出来异或的值和比较的值即可。

b = b'! #"%$\'&'
c = [0x17, 0x84, 0xcd, 0xe8, 0xa9, 0x61, 0xb6, 0xc2]
cmp = [0x74, 0xE8, 0xAF, 0x89, 0xC7, 0x0E, 0xD4, 0xBD,]

print(bytes([ cmp[j]^c[j]^ b[j]for j in range(8)]))

part2

既然都做了第一题,那接下来肯定要看第二题。根据第一题的经验,整体的逆向过程就是vectrexy上用CLI的调试器进行调试,然后对着反汇编出的静态代码和CE里的内存来进行查看。

第一关

目标:吃五个小球,且不被检测出作弊

做法:这关是最明显的,也最简单。 通过CE找到了小球的x,y值,然后通过freeze y的功能实现小球不掉落(但是因为程序好像停的越久下落速度越快,因此如果下方没有板子的话不能长久停止不动,否则还是会掉出范围导致game over)。当把五个egg都吃到的时候这一关就完成了。

反作弊机制:在汇编代码中的$ca60 $ca6a $ca63 $ca6c $ca65几个值在小球碰到egg的时候会分别异或上0x03 ,0x1a, 0x51,0xa9,0xfc。理论上应该这几个值对了就行(我没试过,猜的)

做的时候通过CE找到了记录吃了egg数量的地址,然后就在反汇编出的代码里搜FCB+$55, 找到了5处吃蛋的逻辑。一开始我以为吃完就结束了,撞了一下旗子然后try harder了。再仔细看了一下吃蛋的代码,发现在总数和5作比较以后下面有一个奇怪的值FCB+$53加了1,怀疑就是画面上1/3的1, 于是在代码里搜索了一下。 这才发现了校验部分的逻辑和剩下两关的相关代码位置。

第二关

目标:输入特定的指令(代码在Z1854)

做法:

  1. 第一次左的时候触发$16d3(Z16C0),FCB+$54=1
  2. 第二次再向右,触发Z16FD,FCB+$54=2
  3. 第三次向上(注意是方向键↑不是A),Z1708,FCB+$54=3
  4. 第四次↓方向键,Z17d4,FCB+$54=4
  5. 第五次A键,Z1897,但是是FCB+$54+=1
  6. 第六次还是A,Z1897
  7. 第七次是S,Z1854,FCB+$54+=1
  8. 第八次也是S,同上,
  9. 最后触发Z1854中的cmp 8使轮数加一且FCB+$54=0xff

反作弊机制:应该无

通过上一关找到的代码地址(Z1854),找到关键变量FCB+$54,然后搜索它。大概能看出是要做一串连续的动作,因为一旦做错FCB+$54就会置为0. 又因为这个游戏总共只有8个输入,FCB+$54的值又是能实时看到的,直接人工爆破就行了。

第三关

目标:跳跃次数达到1337

做法: 直接跳1337次 通过CE修改内存进行绕过

反作弊机制: 跳跃次数的值、FCB+$72~$75的值和另一个相关数组(cba8)都要算对

通过第一关找到的代码地址(Z17EB),需要FCB+$75为B7,FCB+$74为78,FCB+$73为70。 FCB+$75,FCB+$74, FCB+$73在Z350E,Z35A5,Z3577等函数里被修改. 尝试在这几个地址下断点,去除每次都会断住的断点,然后发现第一次跳跃会触发Z35A5,之后每次跳跃都会触发Z3577。 逆向这两个函数会发现FCB+$72~$75的值和另外一个数组(cba8)互相影响. FCB+$72为jump次数+0x34. 所以可以还原多次跳跃的逻辑尝试暴力出满足条件的FCB+$73~$75所对应的跳跃次数和数组。最后把得到的cba8数组、跳跃次数和FCB+$72~$75的值都修改成程序解得的值即可。

s = [0xFB, 0xC8, 0xD4, 0x24, 0x18, 0x4F, 0x61, 0x47, 0x33, 0xEE,]


# Z35A5

s[8]= (s[8]+1)&0xff
s[1] = s[8]^s[7]^s[0]
s[6] = (s[6]+s[1])&0xff
s[2] = (((s[6]>>1)+s[7])^s[1])&0xff

e72 = (s[8]+1)&0xff
s[3] = e72^s[1]^s[2]
e73 = s[3]
e74 = (s[6]+e73)&0xff
e75 = (((e74>>1)+s[2])^s[3])&0xff
print(s)
print(e72,e73,e74,e75)

i = 1
# 3577

while True:
    i+=1
    s[0] = (e72 + 1)&0xff
    e72 = (e72 + 1)&0xff
    s[1] = e75 ^ e73
    s[1] ^= s[0]
    e73 = s[1]
    e74 = (e74 + e73)&0xff
    e75 = (((e74>>1)+e75)^s[1])&0xff
    if(e73==0x70 and e74==0x78 and e75==0xb7):
        print(i)
        print(s)
        break;


CE里一些用到没用到的值:
在这里插入图片描述
最后的flag:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值