逆向工程实验Lab1
赞赏码 & 联系方式 & 个人闲话逆向工程前言1、This is a security check to prevent automated programs from creating accounts.2、elfpass3、运行win.pyc,要求输出'You Win'代表成功。4、在windows操作系统下运行cmpy2.exe,要求输出'you are right!'5、c
赞赏码 & 联系方式 & 个人闲话
逆向工程前言
Lab1
1、This is a security check to prevent automated programs from creating accounts.
去下面这个论坛注册一个账号:https://forum.tuts4you.com/
回答出security check问题就可以。This is a security check to prevent automated programs from creating accounts.(这是一个安全检查,以防止自动程序创建帐户。)
代码:
#include<stdio.h>
#include<math.h>
#include<string>
//八进制转十进制
int OtoD(int oct) {
int i, dec = 0, remainder;
for (i = 0;; i++) {
remainder = oct % 10;
dec = dec + remainder * pow(8, i);
if (oct / 10 == 0) {
return dec;
}
oct = oct / 10;
}
}
int main() {
int code[] = { 127,150,141,164,47,163,40,163,150,157,162,164,40,146,157,162,40,42,142,151,156,141,162,171,40,144,151,147,151,164,42,77 };
int i, len;
len = sizeof(code) / sizeof(code[0]);
printf("Code:");
for (i = 0; i < len; i++)
printf("%d ", code[i]);
printf("\nQuestion: ");
for (i = 0; i < len; i++)
printf("%c", OtoD(code[i]));
}
运行结果:
输出内容:
What’s short for “binary digit”?(二进制的简写是什么?)
小结与讨论:
二维码扫出的数字文本,实际上是字符ASCII码的八进制形式。我们要做的是通过编程将其转为十进制,并把对应的字符串输出。
2、elfpass
把elfpass拷贝进seed虚拟机,设成root所有suid程序,用普通用户去攻击获得root权限。可以先静态分析,搞不定再用gdb动态调试。
Step1:设置权限
把elfpass拷贝进seed虚拟机,设置成root所有,赋予suid权限。
Step2:反汇编main函数
通过GDB调试elfpass,使用disas来反汇编main函数,可以看到如下的汇编代码:
注意到里面显示了printf、scanf、strcmp函数,不难推测出分别是用作输出提示语“password”,接收输入的密码以及将输入密码和正确密码的比较。那么在比较前esp和esp+4处放置的就为两个进行比较的字符串的地址。
Step3:设置断点,推测正确密码
我们在strcmp处添加断点,输入任意密码,运行程序。我们首先查看esp得到储存两个字符串的地址。再分别查看两个地址,发现其中一个地址中储存的是我们输入的密码AAAA,另一个地址中储存的应该就是真实的密码。
Step4:确定密码的字符串序列
把得到的ASCII码拷贝进十六进制编辑器中,我们可以把16进制数转换为对应的可显示字符。结合字符串在内存中的存储顺序,我们可以得到密码:unixvswindows。
Step5:验证
3、运行win.pyc,要求输出'You Win'代表成功。
Step1:反编译pyc文件
反编译win.pyc文件,得出以下源码:
Step2:分析py文件
分析源码可得加密公式为((
ord
(v)
+
seed ^
ord
(key[seed]))
%
255
),flag有23位,诸位爆破即可。
Step3:攻击
攻击代码如下:
#include<stdio.h>
#include<string.h>
int main() {
char key1[] = "Maybe you are good at decryptint Byte Code, have a try!";
int key2[] = { 124, 48, 52, 59, 164, 50, 37, 62, 67, 52, 48, 6, 1, 122, 3, 22, 72, 1, 1, 14, 46, 27, 232 };
char simple[] = "QWERTYUIOPASDFGHJKLZXCVBNM{}";
char ch;
int i, j;
int seed = 5;
int tmp;
printf("Flag:");
for (i = 0; i < 23; i++) { //flag有23位
for (j = 0; j < strlen(simple); j++) { //穷举来试
ch = simple[j];
tmp = (ch + seed ^ (key1[seed])) % 255; //原算法的加密方法
if (tmp == key2[i])
printf("%c", ch);
}
seed++;
}
}
运行结果:
4、在windows操作系统下运行cmpy2.exe,要求输出'you are right!'
参考Solving a PyInstaller-compiled crackme:
https://hshrzd.wordpress.com/2018/01/26/solving-a-pyinstaller-compiled-crackme/(上面链接的pyc版本较老,pyc头部缺少8个字节,而下面的cmpy2里面的pyc则缺12字节)在windows操作系统下运行cmpy2.exe,要求输出'you are right!'代表成功。
Step1:解析exe文件
使用工具pyinstxtractor,指令为:python pyinstxtractor.py cmpy2.exe。
输出结果如下:
Step2:修复crackme2文件
解析了cmpy2.exe这个文件后,会生成很多文件模块,这里就有一个名为crackme2的文件。这个文件头部缺了12字节。我们只需将正常的pyc文件的前12字节,复制到crackme2的头部,然后将其另存为pyc文件,即可实现修复。
Step3:反编译pyc文件
在线反汇编:http://tools.bugscaner.com/decompyle/
Step4:攻击
由反汇编的代码可以看出,只要我们第一次输入def,第二次输入1313,程序就能输出'you are right!'。
运行结果:
5、(选做)crackme文件拷贝进seed虚拟机运行,要求输出'Congratulations!'代表成功。
Step1:反汇编crackme
使用IDApro7反汇编crackme,很容易找到这个和明显同密码有关的函数,仔细观察其伪代码,我们可以做出如下分析:
以上分析中有三点需要注意:
①for ( i = 0; v10[i]; ++i ); v1 = i == 19;这两句话如何理解?这里其实是计算v10的长度,若为19则v1为true。主要指明密码长度为19位。
②v5 = byte_804869C[v3];中数组byte_804869C具体是多少?我们可以进一步查看该数组:
这里具体指明了该数组中的20个数据,要注意的是数据在内存中的储存方式,例如0E8D40F58h应为0x58,0x0F,0xD4,0xE8。
③若要输出Congratulations则要保持v1为true,那么就要保持等式v5=v6^v4始终成立。
Step2:求解密码
现在我们的目的是解密出密码,密码是v10,而v10唯一的利用之处就是被赋值给了v6,所以也就是说如果我们找到v6的所有解则找到了最终密码。而v6可以根据等式v5=v6^v4计算,即v6=v5^v4,而v5和v4都是可以通过反汇编出的伪代码知晓的。根据以上分析,编写代码如下:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i;
bool v1;
signed int v2;
int v3;
int v4;
char v5;
char v6;
int v7;
int result;
int v9;
char v10[124];
for (i = 0; v10[i]; ++i);
v1 = i == 19;
//数组byte_804869C
int SS[20] = { 0x6A,0xFB,0x4C,0x8D,0x58,0x0F,0xD4,0xE8,0x94,0x98,0xEE,0x6B,0x18,0x30,0xE0,0x55,0xC5,0x28,0x0E,0x90 };
printf("密码:");
for (i = 0; i < 19; i++)
{
v3 = i;
v4 = 0;
v5 = SS[v3];
v9 = v3 + 1;
v7 = 0;
while (v7 < v9)
{
++v7;
v4 = 1828812941 * v4 + 12345;
}
//v6=v5^v4
unsigned __int8 aaa = (unsigned __int8)v5;
unsigned __int8 bbb = (unsigned __int8)v4;
printf("%c", aaa ^ bbb);
}
printf("\n");
return 0;
}
运行结果:
输出内容:
密码:SesameOpenYourself!
Step3:验证
在虚拟机中运行crackme,输入求得的密码,成功输出'Congratulations!'
更多推荐
所有评论(0)