Windows_Reverse1

0x0 题目涉及知识点

  1. 简单脱壳
  2. 指针运算
  3. 位移量
  4. 字符串查询

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; // ecx
  unsigned int v2; // edi
  unsigned int result; // eax
  int v4; // ebx

  v2 = 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}; // result
    
    unsigned 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}; // result
    
    unsigned 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
在这里插入图片描述
花了好长时间哇,中途去上数据库网课了哈哈。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值