X-NUCA-2019 Reverseme-Clever bird
本帖最后由 Dyingchen 于 2019-8-25 00:19 编辑全国高校网安联赛(National University Cybersecurity Association,简称X-NUCA)是面向全国高校学生的网络安全技能竞赛。
楼主抱着参加玩玩的心情去参加了一下这个比赛,原以为应该能做出最简单的一两道题,没想到直到比赛结束一道也没做出来,话不多说,其中一道比赛题目叫Clever bird
打开程序我们就可以看到一个小游戏
按照常理来说这游戏肯定是过不了关的,所以直接丢入od
既然没壳就直接只能搜索,很快能找到009C1DD6 Your Door, pls key的提示,显然这个位置前面的跳转需要nop掉不然游戏你得一直玩下去过不了关,
然后角色死亡之后游戏会要求你输入一个key
然后就到了逆算法的环节了
大概就是一连串异或运算,逆出算法之后得到我们得到一个key{B1RD},
然后我们把这个key输入到程序里面,得到如下结果
于是到此我认为是结束了,然后把flag放到网站提交却是错误,然后管理给我的答复是这道题我并没有做完,因为刚好要赶火车的原因我就没有继续做下去了,
但是我很迷惑的是程序已经完了啊,一个提示都没有之后该怎么做?希望各位大佬能解一下这个题
Dyingchen 发表于 2019-8-25 11:36
具体算法是什么?
首先要找出进入输入door key的正确分数,我是改他汇编代码爆破出来的,分数是0x20002;
然后前四个字节也如同你们所说的一样算出来是B1RD,第四个字符我一开始也是算不出正确值,但在正确分数下是可以算出第四个是D;
然后将分数0x20002转二进制字符串并且反转,然后两者拼接在一起就好了 本帖最后由 梦游枪手 于 2019-8-25 15:39 编辑
跟楼上大佬说的一样,带上door的目标分数就行了
目标分数计算过后得到结果为0x436AE,要暴力还原应该也是可以的,不过这个过程涉及到浮点转换,还是推荐改汇编拿到计算前的score,这样更简单点。
丢个暴力破解的py脚本吧。
import ctypes
def h2f(s):
cp = ctypes.pointer(ctypes.c_int(s))
fp = ctypes.cast(cp, ctypes.POINTER(ctypes.c_float))
return fp.contents.value
def f2h(s):
fp = ctypes.pointer(ctypes.c_float(s))
cp = ctypes.cast(fp, ctypes.POINTER(ctypes.c_int))
return cp.contents.value
if __name__=='__main__':
X=0
score=0
while(int(((1.5-h2f(X)*h2f(X)*(score/2))*h2f(X)*100000000*10+5)/10)!=0x436AE):
score+=1
X=0x5F3759D8 - (f2h(score)>>1)
if X!=0:
X+=7
print score
至于楼上说的解密出来的结果为B1R2的,我的解密key是0xA991E504,脚本如下
if __name__=='__main__':
key=0xA991E504
b=
out=''
for i in range(len(b)):
out+=chr((b^((key>>(i*8))%0x100))+0x30)
print out
0xA991E504是异常处理分支返回,这个值是程序读取自身计算出来的,算是一个自校验,你应该是修改了程序吧。
@梦游枪手 二楼艾特大佬 附件不小心被我编辑删除了,重新传一下吧。 flag是"B1RD1"吧,程序有判断第五位是不是"1"的,我输入BIRD过不了 梦游枪手 发表于 2019-8-25 01:01
flag是"B1RD1"吧,程序有判断第五位是不是"1"的,我输入BIRD过不了
可是奇怪的是程序在我输入B1RD之后也显示成功了,输入B1RD1也是成功 Dyingchen 发表于 2019-8-25 07:54
可是奇怪的是程序在我输入B1RD之后也显示成功了,输入B1RD1也是成功
我看不懂你们的D是怎么算出来的我算出来的是一个2次方的符号
d = #ebp+esi*4-0x48
ebx = # ebx3f91e504
for i in range(4):
raw = (d ^ ebx)+0x30
print(chr(raw), raw)
""" 输出
B 66
1 49
R 82
2 178 <= 这个2次方符号输入控制台也是当作数字2处理
无论怎么输入 根本就执行不到 congratulation,submit with format: flag{key}
除非改那个jnz跳转 改成jz 输入什么都是对的
""" syncking 发表于 2019-8-25 08:07
我看不懂你们的D是怎么算出来的我算出来的是一个2次方的符号
d =
可是输入B1R2程序直接输出wrong了 Dyingchen 发表于 2019-8-25 08:14
可是输入B1R2程序直接输出wrong了
但是输入B1RD 和 B1RD1也是错误的
本帖最后由 syncking 于 2019-8-25 08:35 编辑
00161E80 > /0FBE5435 C8 movsx edx,byte ptr ss: ;edx 代表是输入的数据
00161E85 . |8BC3 mov eax,ebx ;ebx 3F91E504
00161E87 . |D3F8 sar eax,cl
00161E89 . |83EA 30 sub edx,0x30
00161E8C . |0FB6C0 movzx eax,al
00161E8F . |33D0 xor edx,eax
00161E91 . |3954B5 B8 cmp dword ptr ss:,edx ;要对比的数据分别是0x16 0xE4 0xB3 0xBD
00161E95 |75 30 jnz short Clever_B.00161EC7 ;不相等就跳转到 error
00161E97 |83C1 08 add ecx,0x8
00161E9A |46 inc esi
00161E9B |83F9 20 cmp ecx,0x20 ;这里限制了只比较了 4位
00161E9E .^\7C E0 jl short Clever_B.00161E80
00161EA0 .8B0D 98401600 mov ecx,dword ptr ds:[<&MSVCP140.?cout@s>;msvcp140.?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A
00161EA6 .BA 30431600 mov edx,Clever_B.00164330 ;congratulation,submit with format: flag{key}
00161EAB .68 20261600 push Clever_B.00162620
00161EB0 .E8 2B050000 call Clever_B.001623E0
刚刚我写的那个python脚本 算出来的第四个数据也只有2次方符号 符合答案
程序输入B1R2是错的,控制台输入B1R2次方 ,这个2次方符号从这个程序汇编上看是按ASCII(32)对待的。所以怎么输入也不会对
我觉得就是出题的人就是不想让你通过输入得到数据所以用了一个2次方符号的数据
其他的我就不知道 一个菜鸟的分析 syncking 发表于 2019-8-25 08:26
00161E80 > /0FBE5435 C8 movsx edx,byte ptr ss: ;edx 代 ...
x-30^4=16 B 10进制 66 16进制 42即42-30^4=16
x-30^E5=E4 1
x-30^91=B3 R
x-30^A9=BD D
没有问题啊,我发现好像每个人的机器上面运行都有差异,难不成是我一开始的思路就错了?