MRCTF逆向 MR_register.exe

MRCTF的MR_register.exe复现

首先先用exeinfope查一下壳
在这里插入图片描述
没有加壳,64位的程序 ,拉入ida64进行分析
在这里插入图片描述
这两个肯定有一个里面有主函数,我们都点进去看看
sub_402E50()
在这里插入图片描述
确实看不出什么东西
sub_401180()
在这里插入图片描述
往下翻翻,看到initenv 初始环境的意思,所有main函数很可能在下面
继续跟sub_4015F0()
在这里插入图片描述
这题其实是个双线程问题,就是父进程(else后的内容)执行后,担任调试器的角色,去调用if中的 sub_4026EA()函数

注意一点:
当我们在调试这个程序的时候,会有报错
在这里插入图片描述
这里报错的原因应该是分母为0导致的
在这里插入图片描述
在子进程中V19=1,打印出flag
所以关键是看DebugEvent.dwDebugEventCode == 1的活动:接受处理来自子进程的异常,进而修改子进程代码
在这里插入图片描述

SMC的题目,我们就让它自己跑起来解密就行了

关键代码还是在调试的子线程中,我们分析一下

为什么会程序自报错?
原本两个进程是互不相关的,当子进程产生错误后,返回给父进程,父进程才知道要进行处理了,但是也不是一直处理,所以就会出现另外一个错误,告诉父进程处理完了,可以停止了。

所以现在关键就是要去寻找子进程要执行函数中出现触发异常地方
在这里插入图片描述
继续分析子进程
在这里插入图片描述
加密逻辑主要就关注到sub_401CA7
在这里插入图片描述
点进去是这样的,我们发现很多代码被混淆了
在这里插入图片描述
这里前面会有int 3触发断点,后面还有很多错误指令,实际是一个smc,那可以猜到就是先触发断点后被主进程调试器所捕获,然后进行解密,之后被调试进程继续运行

我们写脚本跑一下SMC,这里直接贴上官方WP的脚本
下面展示一下

#include <idc.idc>

static main(){
    auto addr = 0x401E1F;
    auto i = 0;
    for(i=0;i<0x57E;i++){
        PatchByte(addr + i,Byte(addr + i) ^i);
    }
}

在这里插入图片描述
在函数开头按d 解析成数据
将黄色部分全部选中 按c 解析成代码
在这里插入图片描述

将int 3 nop掉
在这里插入图片描述
我们发现rip+2
直接跳到两个字节之后,patch混淆的三个字节
现在所有代码都红了,直接全选,按p创建函数,f5反编译
在这里插入图片描述
加密代码就出来了
返回之前的子进程中看了下传参,第一次参数密钥credentials,第二个是email

在这里插入图片描述
这是加密流程
加密操作不复杂,查看验证函数
在这里插入图片描述
在这里插入图片描述
就是把邮箱密文和密钥密文按照-的分割来分别读取出来,最后把密钥最后一次与邮箱密文的异或加密给异或回去,经过这个解密操作后进行比较
在这里插入图片描述

但是这还没完,因为这个验证数组是被修过的,在主进程进行调试的某一时刻会重新修改此处内存,这一部分的实现主要是通过管道通信和环境变量的设置来完成的

子进程在这里活得自己进程check数组的储存位置后利用v24/=Buffer[19]触发除零异常,在这之前讲内存地址用writefile写到管道中,子进程捕获异常后获取地址,修改内存位置的值,处理异常,子程序继续执行,但是check数组已被改变。

在这里插入图片描述

在这里插入图片描述
处理除零异常,此处sub_402545进行修改内存,进行了加花,patch即可,改call+ret+pop为jmp即可
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
对内存进行了一次异或操作

大概就分析完了,其实还是挺有难度的,我的思路也比较乱,把网上各位师傅的WP都翻看了下,进行了总结
最后贴上大师傅的脚本

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


void map(char key,int *x,int *y){
    int i = 0,j = 0;
    char table[9][9]={'\0'};
    strcpy(table[0],"ABCDEFGH");
    strcpy(table[1],"12345678");
    strcpy(table[2],"0IJKLMNO");
    strcpy(table[3],"+OPQRStu");
    strcpy(table[4],"\\vwxyzTU");
    strcpy(table[5],"abcdefgh");
    strcpy(table[6],"VWXYZijk");
    strcpy(table[7],"lmnopqrs");
    for(i=0;i<8;i++){
        for(j=0;j<8;j++){
            if(table[i][j]==key){
                *x = i;
                *y = j;
                return ;
            }
        }
    }
}

int main()
{
    int x,y,z;
    int count = 0;
    int i = 0,j = 0,k = 0;
    char tmp[10]={'\0'};
    int result[100]={0};
    char plain[376]={'\0'};
    int flag[376]={29,110,78,63,57,58,40,41,23,20,55,70,67,48,17,18,45,46,2,12,48,49,50,62,37,38,5,118,94,45,15,12,29,30,63,76,102,
        21,56,59,21,22,6,117,111,28,3,0,13,124,127,3,16,108,122,11,5,6,42,43,33,82,125,14,80,83,127,124,91,90,86,88,108,16,6,119,113,114,
        80,81,125,14,17,98,120,123,107,104,118,120,126,112,113,112,67,64,93,81,70,58,5,121,66,76,121,122,87,38,35,95,74,68,109,108,108,111,
        73,74,102,103,84,90,94,80,99,98,82,81,189,190,157,156,169,168,151,153,173,209,198,183,177,178,144,227,220,160,183,185,139,138,187,184,
        165,166,183,182,130,241,221,174,190,176,134,138,153,232,229,150,184,185,180,199,225,146,128,131,141,142,162,163,165,164,171,216,247,132,
        148,231,241,128,131,128,208,163,129,242,233,232,217,216,230,231,213,214,241,242,209,162,147,146,144,227,196,197,201,200,199,196,231,228,
        193,192,240,241,240,241,252,143,166,213,248,251,213,214,199,180,141,140,163,208,222,223,236,237,233,234,203,186,186,201,231,148,176,204,
        219,213,46,47,44,47,57,58,22,23,23,22,23,25,41,85,65,64,82,46,55,59,41,42,6,117,84,40,63,49,48,62,58,52,13,126,110,31,25,26,57,74,73,72,
        101,22,60,61,2,12,21,105,126,15,9,10,43,88,116,7,22,24,25,23,47,46,109,30,0,113,121,122,106,25,4,119,100,23,15,115,106,100,77,76,66,65,105,
        24,27,26,27,26,22,101,66,76,122,6,45,44,46,95,89,90,118,119,117,123,78,64,115,0,33,82,96,110,86,42,54,71,75,120};

    for(i=374;i>=0;i--){
        flag[i] = flag[i] ^ i ^ flag[i+1];
    }
    for(i=0;i<376;i+=2){
        map(flag[i],&x,&y);
        map(flag[i+1],&y,&z);
        plain[j++] = ((x << 6)|(y << 3)|(z));
    }
    j = 0;
    for(i=0;i<strlen(plain);i++){

        while(plain[i+j]!='#'&&plain[i+j]!='\0'){
            j++;
        }
        strncpy(tmp,plain+i,j);
        result[k++] = strtoul(tmp,0,16);
        count++;
        i = i+j;
        j = 0;
    }
    for(i = count-1;i>=2;i--){
        result[i] = result[i] - result[i-1] - result[i-2];
    }
    for(i=0;i<count;i++)
        printf("%c",result[i]);

    return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值