本文主要是介绍Windows_Reverse1,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
- 0x0 题目涉及知识点
- 0x1 查壳脱壳
- 0x2 反汇编分析
- 0x3 写脚本
0x0 题目涉及知识点
- 简单脱壳
- 指针运算
- 位移量
- 字符串查询
0x1 查壳脱壳
使用 UPX 工具脱壳
0x2 反汇编分析
初步了解程序执行流程,sub_401000(&v6)
为加密过程,&v4中存放了flag。
char v4; // [esp+4h] [ebp-804h]char v5; // [esp+5h] [ebp-803h]char v6; // [esp+404h] [ebp-404h]char Dst; // [esp+405h] [ebp-403h]v6 = 0;memset(&Dst, 0, 0x3FFu);v4 = 0;memset(&v5, 0, 0x3FFu);
这两句有一些特殊,是以Dst和V5的地址为数组首地址,创建0x3FF大小缓冲区用于存放数据。
可视化分析流程,得到 you have got it
逆向就完成。
中间部分是我们需要逆向分析的算法,算法中有一个向上的跳转作为循环
scanf("%s", &v6);
sub_401000(&v6);
输入字符串,并将地址传入 sub_401000()
unsigned int __cdecl sub_401000(const char *a1)
{_BYTE *v1; // ecxunsigned int v2; // ediunsigned int result; // eaxint v4; // ebxv2 = 0;result = strlen(a1);if ( result ){v4 = a1 - v1;do{*v1 = byte_402FF8[(char)v1[v4]];++v2;++v1;result = strlen(a1);}while ( v2 < result );}return result;
}
以上为IDA反汇编结果,因为涉及到指针的计算,直接从反汇编代码中无法理解 v1
v4
的作用,所以打开OD进行动态调试。
通过调试发现,v4的值是定值 sub ebx,ecx ⇒ ebx = 0x400
循环中,eax中存放一个byte的数据,来自ds:[ebx + ecx]
发现 ebx(0x400) + 0xecx
ecx每次都自增1,这正好是我们输入字符串的地址。
总结过程:
遍历输入的字符串,获取每个字符转为整数A,在常数数组获取下标为A的字符放入*V1中,每次V1指针都自增1
发现通过OD无法直接访问到0x402FF8
数据,但是访问 eax + 0x402FF8可以访问到数据,可以看出是一个字符串,所以直接在IDA中查看String,发现真正的地址为0x00403018
,存在0x20
的位移
通过IDA获取加密字符串
.data:00403018 00000060 C ~}|{zyxwvutsrqponmlkjihgfedcba`_^]\\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#\"!
通过以上分析,重写反汇编代码,让自己可以直接调试这个算法。
#include<iostream>
#include<string>
using namespace std;
string byte_402FF8 = "~}|{zyxwvutsrqponmlkjihgfedcba`_^]\\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#\"! ";
unsigned int sub_401000(string inputArray)
{char v1[100] = {0}; // resultunsigned int cnt = 0;unsigned int inputLen = inputArray.length();cnt = 0;do{v1[cnt] = byte_402FF8[(char)inputArray[cnt] - 0x20];++cnt; }while ( cnt < inputLen );v1[cnt] = '\0';cout <<v1;return inputLen;
}int main(){sub_401000("123456");
}
最后运算结果与字符串DDCTF{reverseME}
比较是否相等
0x3 写脚本
我们要做的就是将字符串 DDCTF{reverseME}
重新映射到输入
#include<iostream>
#include<string>
using namespace std;
string byte_402FF8 = "~}|{zyxwvutsrqponmlkjihgfedcba`_^]\\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#\"! ";
unsigned int sub_401000(string inputArray)
{char v1[100] = {0}; // resultunsigned int cnt = 0;unsigned int inputLen = inputArray.length();cnt = 0;do{v1[cnt] = byte_402FF8[(char)inputArray[cnt] - 0x20];++cnt; }while ( cnt < inputLen );v1[cnt] = '\0';cout <<v1;return inputLen;
}int find_index(char s){for(int i=0;i<byte_402FF8.length();i++){if(s == byte_402FF8[i]) return i;}cout <<"error"<<endl;return -1;
}string reverse(string result){char input[100];int i;for(i = 0; i < result.length() ;i++){int index = find_index(result[i]);input[i] = (char)index + 0x20;}input[i] = '\0';return string(input);
}int main(){string flag = reverse("DDCTF{reverseME}");cout << endl << "flag{" << flag << "}" << endl;sub_401000(flag);
}
拿到flag
花了好长时间哇,中途去上数据库网课了哈哈。
这篇关于Windows_Reverse1的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!