我选取了两条实验吧里的逆向题目,题目不是很难,对于刚刚入门逆向的人来说,我觉得十分有用,由于自身逆向水平有限,有很多地方自己也是一知半解,不多说,开始我的表演~
1.该题不简单
下载压缩包的程度解压后得到一个exe文件,打开运行之
可以看到hello是我们用户输入的,而注册码会通过本身的函数来计算获得,这时候我们就需要逆向程序,去看看它的加密函数是什么,然后根据这个加密函数来计算这个注册码~
首先我们要看这个程序有木有加壳,没有加壳,开始我们的逆向之路!
找到他的加密方式
1
2
3
4
5
6
7
8
9
10
11
12
|
if ( strlen(String) != 0 )
{
do
{
*(&String2 + v1) = (v1 + v1 * String[v1] * String[v1]) % 0x42 + 33;
++v1;
}
while ( v1 < strlen(String) );
}
strcpy(String, “Happy@”);
lstrcatA(String, &String2);
result = lstrcmpA(&String1, String) != 0;
|
找到了下面我们开始分析,这个String是我们输入的字符串,String2初始为0,v1初始为0,下面进入循环,我们输入Hello(后续发现hello错误,因此H要大写),整个字符串就成了Hello,这时候v1作为一个计数器,实现对我们输入字符串的每一个字母的加密,又由于指针的作用,*(&String2+v1)可以实现对每个内存单元的操作,因此也就实现对每个字母的操作,继续看后面的加密方式~
v1为字母的位置,String[v1]为字母的ascii码值,然后有一个除余操作,最后再加上33
这里我们的加密方式就已经结束,总的来说就是
v1+(v1*字母的ascii码*字母的ascii码)%0x42+33
然后再计算完每一步,最后在前面加上一个Happy@
python脚本
1
2
3
4
5
6
7
8
9
|
#-*-coding:utf-8-*-
username=‘Hello’
count=0
password=‘Happy@’
for i in username:
password+=chr((count+count*ord(i)**2)%0x42+33)
count+=1
print password
|
2.证明自己吧
下载exe文件,打开尝试之
要我们猜密码,,爆破?不存在的。。老老实实逆向去吧
首先看有没有加壳,没有加,赤裸裸的c程序~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
int __cdecl main(int argc, const char **argv, const char **envp)
{
int result; // eax@2
int v4; // [sp+0h] [bp-7D0h]@1
sub_4011BA(aCanYouGuessThe, v4);
gets((char *)&v4);
if ( sub_401060(&v4) )
{
sub_4011BA(aGoodTheKeyIsYo, v4);
result = 0;
}
else
{
sub_4011BA(aYouDonTGuessIt, v4);
result = 0;
}
return result;
}
|
看这里的main函数,主要看if语句,我们可以猜测如果密码正确那么,就会跳到一个程序段,如果错误,就是另一个程序段,因此这里的函数名也稍有提示,一个是aGoodTheKeyIsYo,失败的话则是aYouDonTGuessIt,那么我们接下来要重点关注if的判断语句,为sub_401060,接下来我们跳转到这个程序段,去进一步分析他的加密原理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
if ( strlen(a1) == strlen((const char *)&v5) )
{
v1 = 0;
if ( strlen(a1) != 0 )
{
do
a1[v1++] ^= 0x20u;
while ( v1 < strlen(a1) );
}
/*第一个程序段*/
v2 = 0;
if ( strlen((const char *)&v5) != 0 )
{
do
*((_BYTE *)&v5 + v2++) -= 5;
while ( v2 < strlen((const char *)&v5) );
}
/*第二个程序段*/
v3 = 0;
if ( strlen((const char *)&v5) == 0 )
return 1;
while ( *((_BYTE *)&v5 + v3 + a1 – (const char *)&v5) == *((_BYTE *)&v5 + v3) )
{
if ( ++v3 >= strlen((const char *)&v5) )
return 1;
}
/*第三个程序段*/
}
|
下面我们开始分析程序段!
首先我们看第一个程序段,首先这里我们需要看循环条件,a1的长度等于v5地址段数据的长度,这里我们又需要去查看以下v5的数据
学过汇编的都知道DW所占用的是四个单元,因此,这里的v5数据为68571948、506E5878、546A1958、5E06,第一个函数段十分简单,将v5中的每一个数据与0x20进行一次异或运算即可
第二个程序段也十分简单,对v5中的数据进行一次减5的运算即可
第三个程序段的while函数中好像了混淆,不过我们经过抽丝剥茧,我们可以直接相当于a1=v5,其实这个程序段对结果没有任何影响
最后我们也就能得到的我们的加密函数
1.str=str^0x20
2.str-=5
附上Python脚本
1
2
3
4
5
6
7
|
#-*-coding:utf-8-*-
import sys
code=(0x68,0x57,0x19,0x48,0x50,0x6e,0x58,0x78,0x54,0x6a,0x19,0x58,0x5e,0x06)
for i in code:
i=i^0x20
i-=5
sys.stdout.write(chr(i))
|
最后得到我们需要猜测的字符串~
题目链接:传送门 密码学不多,就三条,作为一个信息安全学生,密码学什么的最简单了~ 1.哼哼 小猪生活的地方在哪里? ★tip:yitctf{内容为小写} 小猪,联想到猪圈密码,百度详解地址:传送门 根据字符对应可知flag为HACK 2.卢本伟 LOL我只服…
请登录后发表评论
注册