本文为之前参加过的ctf比赛的writeup,迁移到这个博客来吧

RE

slime_war(solved)

  • 刷了全图竟然只有2?还是乱码
  • 经典一道题玩一天,感觉得练一下密码学,不然只做逆向还是不太行;
  • 自己搞了一天,在共享文档上和龙哥交流,慢慢把条件给理顺了,经典的控制台程序编程,没有套框架,代码用IDA看都非常好懂,感觉应该是我比较能做的一类题目了;
  • 题意是玩一个游戏,收集5个隐藏条件最后出flag;
  • 首先是改攻击力,走了一圈打了全图,发现通关后并没有flag,看代码发现有一个变量被不同的地方累计了5次,直接xref然后每个变量增加的地方都下个断点,然后再玩一次,把原来打的2给定位了,发现:
  • 第一个在0x1400066B0的地方,在第七层有一个隐藏奖励获取的地方,打穿然后回到第一层,进去隐藏关卡再出来触发;
  • 第二个应该就是打通boss,但是这里并不是唯一的条件,后面再说;
  • 第三个是键盘输入,接下来就是看剩下的断点,其实从这里开始才在认真看程序,第一个是类似一个作弊码要输入一个东西,在龙哥的提醒下发现程序根据键盘的输入逐渐对一个状态值继续累加(龙哥提醒:状态机),所以说看一下程序可以把这个值看出来,这样输入就变成了一个字符串作为密码的一部分;
  • 第四个,把攻击力计算一下然后和一个常数比较,搜了一下常数应该是md5,但是在爆破的时候犯了个很蠢的错误,hashlib.md5直接使用了update更新每一个种子,应该每次都得重新声明一个新的md5()orz,这一步卡了有点久,太蠢了;
  • 第五个: 0x14000632D的那个,第三层买药水,第二层站在19列4行按t进去,不能走错,29步走到T,这一个对应的条件是走到T点,当时在第二层看到了T点但是进不去,仔细看了下变量发现其实是有提示的,另外还有一个是说当时盲目找还以为是有什么特殊的砖块,结果走了半天并没有;
  • 到这里打了boss以为过关了,结果5个secret但是boss那里打出来的还是乱码,在龙哥的指导下仔细看了打完boss的条件,一开始对里面计算时候的变量xref了一下看引用,没有发现在其他变量的地方使用,但是有一个地址的常数被用来把整个程序的text段(0x9000个bytes)拿去做了一个类似hash的操作,然后把这个hash值作为密码写到目标的地方;
  • 但是我用ida调试的话发现这个值是算不对的,很奇怪,改的几个攻击力啥的xref看了也没放在text段上,为啥用ida调的和自己提取出来算的不一样呢(算出来的值是3601301130,放进v47)->龙哥:下了软断点之后程序就会变化;
  • 但是ida里面看不出来诶感觉,看来还是太依赖工具了;
  • 总结下这道题,题目比较经典,自己太菜,基本技能还不行,没啥脚本,就放一下那个算常数的代码吧;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
#include<fstream>
using namespace std;

unsigned char a[0x9000]={0x48,0x8D,0x5}; // too much

unsigned int d[320]={0x0,0x77073096}; // too much

int main(){
unsigned int v48=0;
unsigned long long v49=0;
unsigned char v50=0;

do{
v50=v48^a[v49];
v49+=1;
v48=(v48>>8) ^ d[v50];
}while (v49!=0x9000);

cout<<v48<<endl;
return 0;

}