实战:绕过我的密码校验
实战:绕过我的密码校验
这次我要破解我大一课程作业做的雷霆校园社团系统,虽然说什么admin的密码都是放在txt文件里的,但是办法总比困难多,我之前一时兴起,在自己的系统的密码校验里面加了个硬编码的彩蛋密码,这次我们的目标就是这个
……因为这系统是我手搓的,所以当我打开字符串的时候我都大概知道这些是什么玩意,直接就找到我的彩蛋了,没意思啊,我决定还是按照正常思路来破解……等下,我的账号密码明文记录的,进这系统到底有什么意思啊!
算了,先看看字符串,不过我倒是发现了,要是项目大起来,可能搜个字符串都要搜很久,我的小系统字符串倒是不多,暂时先继续用字符串定位

看到一堆admin,直接根据里面的路径../data/admin.txt去找一下admin的账号密码,而我的文件树简单到离谱——加上头文件只有八个,数据文件也只有五个,接着密码就轻松被找出来了,txt甚至不需要任何破译(
还是稍微尊重下自己的劳动成果吧(
我们可以看到现在中文的字符串都是乱码,估计还是因为编码问题,这个dbg工具这个页面没有utf8的显示,github上是有插件的,但是这次没装,准备直接用命令utf8 ()来查
不过可以我们先看看我在哪里用了../data/admin.txt这个路径,跳转一下

我们发现后面下面好像紧接这个字符串,我们看一下内容是啥,命令行输入utf8(40A9B8)

发现是个没啥用的兜底(
看来这样胡乱试错不太可行,我决定换个思路
我的思路非常神秘,我决定先随便试下错,看看直接填错误的账号密码会出现什么:

好的我知道了,那我们根据这个提示语的格式,看看能不能找到对应的字符串:

直接筛选感叹号,欸,字符数不兑啊,什么情况,我们转utf8看看;

神秘,虽然过程不太对,但是我们找到了登录成功的提示,现在我们跳转过去
还是看不懂啊!

这里有两个字符串,转编码后都是登录成功,剩下两个应该是给普通用户用的,但是我突然想起来,我好像一个没有看过scanf是怎么输入数据的,这是整个系统交互的核心啊
c
复制代码
#include<stdio.h>
int main()
{
printf("yulabu");
int x;
scanf("%d", &x);
if(x == 2){
x = 1;
}else{
x = 2;
}
return 0;
}
浅浅尝试了一下,感觉也没什么不得了的:

初始化一个x,将[rbp-4]位置的空间用来放这个变量,计算404007这个地址,把这个地址放在rcx,然后call的时候rcx传入scanf,scanf应该会把我输入的值存入这个地址指向的空间(我估计rdx也是传入scanf的参数),反正最后我们输入的数应该是传到eax了(最后断点测试确实传到rax了)
实际参数应该如下:
复制代码
RCX = "%d"
RDX = &x
接下来就是个简单的if-else,现在我们大概知道这个scanf如何工作的了,再回到我们原来的程序看看:
根据字符串定位,我找到了之前留下的一些很接近登录入口的地方:

我们来看下附近的反汇编,重点看看有没有scanf的调用,本来按照正常思路,我要正常这样逆向下去的吧,但是这程序是我自己写的,所以我大概知道对应字符串都干了什么(

这一步应该就是一个登录确认或者什么的,第一行的字符串没有注释,我们直接根据地址utf8一下

好样的……等下,这有啥用啊,算了,我们还是继续找引用吧(
不是引用也不好找啊,于是我胡乱看这些模块跳转的位置,最后发现一个strcmp

感觉很像是密码校验啊!但是我用断点检测的时候根本没有跑到这里,可能和登录没关系

再去字符串搜索admin,发现有个admin 123,根据我的记忆,这就是初始化密码(
好家伙直接登录进去了(

这一部分我是有印象的,首次运行生成的初始管理员账密(
到这里就结束了吗?我的系统也太没意思了吧,嗯,那再找找我之前的硬编码彩蛋:

这两个怎么看都像是彩蛋,跳转过去看看:

然后发现两层校验,真的和账号密码很像,这里还有个test,刚好补上了之前没有test的空缺
(又去和神沟通了一下)
神告诉我,strcmp在windows x64下,rcx和rdx分别是第一个参数和第二个参数,这个strcmp的返回值放在eax,返回0则说明字符串相等(校验成功),于是就有以下test:
asm
复制代码
test eax,eax
(发现gpt是啥子,最后自己翻别人博客😡)
其实cmp和test的功能很像,只是实现的方法不一样:
CMP属于算术运算指令,用于比较两个值(寄存器,内存,直接数值),对两个操作数做减法后仅修改标志位,不回送结果
test属于逻辑运算指令,执行BIT与BIT之间的逻辑运算(两操作数作与运算,仅修改标志位,不回送结果)
以下两个操作有相同效果:
asm
复制代码
test ax,bx
and ax,bx
至于修改标志位是干嘛,就理解成给下面的有条件跳转提供一个校验的条件,原理又要涉及状态寄存器,这章先不搞
所以搞了半天,这一句test实际上是在校验eax是不是0
如果是0的话,说明字符串相同,校验成功,下一步的跳转取消,直接继续往下执行:
asm
复制代码
lea rax,qword ptr ss:[rbp-40]
mov rdx,rax
lea rcx,qword ptr ds:[40A37F]
call <JMP.&strcmp>
test eax,eax
jne main.401BDA
这里一看就知道是rax把之前输入的密码所在的地址给计算到rax里面去了,然后这个40A37F存的就是我的彩蛋密码:love
依旧传入参数,返回eax,校验,最后通过!

这个指令也确实跑到这里来了,我们一路下去,下一个断点的位置应该就是初始化管理员操作界面了
如果我要改彩蛋,直接跑到存这两个彩蛋的位置直接修改就可以了,硬编码彩蛋还是太蠢了,而且明文存储的admin账密!直接根据开局找到的路径去改就完事了!我当时真是个天才!
总结:这大一95分的大作业就是个没鸡毛用的玩具(
评论