安洵杯2023 RE 你好PE WP

本文详细描述了作者在反编译过程中追踪加密主函数的过程,涉及静态分析、调试和发现加密算法的关键步骤,最终通过官方脚本揭示了加密逻辑和密钥。
摘要由CSDN通过智能技术生成

反编译时遇到一点问题……所以复现也不完全

无壳32位

寻找加密主函数

先静态分析往下跟

注意12行sub_44E753第一个参数是0,第二个参数是疑似输入内容IpAddress,跟进去

这里只会触发case 0

这里上文a1是IpAddress,涉及到它的函数是sub_44FCC5

出现了IpAddress的大量引用,不知道哪个有用,动调尝试

会发现只有19行sub_44ED5C运行后会有字符串输出的变化

仔细调试会发现应该是在14行位置跳转至真·主函数

下个断点继续动调

F7进入,然后F8到这里停了,打个断点重启

再来一次

跑进主函数了

往上翻,在主函数开头部分按P形成函数,然后F5分析

通过len error的字样,我们可以猜测第一个if判断的是字符串长度,猜一下长度为41(紧接着41被改成48,根据答案格式可以猜测,增加的7个字符应当是 D0g3{}和'\0',输入的仅仅是括号内的部分)

我们也可以进17行确认一下

显然是在计算flag长度

然后找一下加密函数

这里22行应该是字符串比较,unk_1013C008点进去就是密文(注意密文对比用了48个字符,从4D往下48个都是密文)

(1013C008)16+(48)10 =(1013 C038)16

整理一下可得密文:

0x4D,0xB8,0x76,0x29,0xF5,0xA9,0x9E,0x59,
0x55,0x56,0xB1,0xC4,0x2F,0x21,0x2C,0x30,
0xB3,0x79,0x78,0x17,0xA8,0xED,0xF7,0xDB,
0xE1,0x53,0xF0,0xDB,0xE9,0x03,0x51,0x5E,
0x09,0xC1,0x00,0xDF,0xF0,0x96,0xFC,0xC1,
0xB5,0xE6,0x62,0x95,0x01,0x00,0x00,0x00,

F8到21行F7进去

照例P然后F5反编译(和官方跑出来不一样!红温了!8.3我也试过了,也不一样)

qword_1013C000是一个被异或的部分,应该是某种密钥

其值为54AA4A9

我这个伪代码和答案有出入,编不出来……拿官方的函数写脚本吧

抄一下官方的脚本进行分析

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Windows.h>

void fdec()
{
    __int64 dq_key = 88777897;  //用于异或的key(54AA4A9)
    BYTE flag[] = {
        0x4D,0xB8,0x76,0x29,0xF5,0xA9,0x9E,0x59,
        0x55,0x56,0xB1,0xC4,0x2F,0x21,0x2C,0x30,
        0xB3,0x79,0x78,0x17,0xA8,0xED,0xF7,0xDB,
        0xE1,0x53,0xF0,0xDB,0xE9,0x03,0x51,0x5E,
        0x09,0xC1,0x00,0xDF,0xF0,0x96,0xFC,0xC1,
        0xB5,0xE6,0x62,0x95,0x01,0x00,0x00,0x00,
    }; //密文
    __int64 p;
    int j, i;
    for (i = 0; i < 6; i++)  //48/8=6轮
    {
        p = *((__int64*)&flag[i * 8]); //每次取8位,形成一个块构成整数
        for (j = 0; j < 64; j++)  //64次加密
        {
            if (p & 1) //就是判断是否>0
            {
                p = ((unsigned __int64)p ^ dq_key) >> 1; //异或之后右移一位
                p |= 0x8000000000000000;//还原符号位1 

            }
            else
            {
                p = (unsigned __int64)p >> 1;  //直接右移一位
            }
        }
        *((__int64*)&flag[i * 8]) = p; //加密之后赋值回去
    }
    for (i = 0; i < 48; i++)  //全部打印出来
        printf("%c", flag[i]);
    printf("\n");
    return;
}

int main(int argc, BYTE* argv[])
{
    fdec();
    return 0;
}
  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值