mrctf的wp

后面来做的题。做了2道半,后面就是看wp学习了,复现了5道,学到了很多新知识,其他人wp写的很详细,就不贴图片了,太懒了。

其他人的wp

官方

usher

wjh

bxb0

real_signIn

变表base

import base64
import string

str1 = "tvjdvez7D0vSyZbnzv90mf9nuKnurL8YBZiXiseHFq=="

string1 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

print (base64.b64decode(str1.translate(str.maketrans(string1,string2))))
# MRCTF{wElc0Me_t0_MRCTF_2o21!!!}

dynamic_debug

动调就可以看到整个大致过程了,是tea加密

tea加密

//  0x99, 0xA1, 0x85, 0x55, 0x68, 0x5D, 0x82, 0x7E, 0x39, 0x00, 
//  0x4D, 0x94, 0x43, 0x69, 0x72, 0x71, 0x06, 0x43, 0x51, 0x6A, 
//  0x00, 0xAD, 0x14, 0x4B, 0x3F, 0x0D, 0xD2, 0x64, 0x15, 0xDB, 
//  0x37, 0x9F
//MRCTF{aaaaaaaaaaaaaaaaaaaaaaaaa}
//0x5585A199, 0x7E825D68 944D0039 71726943 6A514306 4B14AD00 64D20D3F 9F37DB15
#include<stdio.h>


void decrypt(unsigned int *code , unsigned int *key)
{
    unsigned int delta=0x9e3779b9;
    unsigned int v0,v1,sum=delta*32,i;// sum=0xC6EF3720

    v0=code[0];
    v1=code[1];
    for(i=0;i<32;i++)
    {
        v1-=( (v0<<4)+key[2] ) ^ (v0+sum) ^ ( (v0>>5)+key[3] );
        v0-=( (v1<<4)+key[0] ) ^ (v1+sum) ^ ( (v1>>5)+key[1] );
        sum-=delta;
    }
    code[0]=v0;
    code[1]=v1;
    for(i=0;i<2;i++)
    {
        printf("%c%c%c%c", *((char*)&code[i])&0xff,*((char*)&code[i] + 1)&0xff,*((char*)&code[i] + 2)&0xff,*((char*)&code[i]+3)&0xff);
    }
}

//0x944D0039, 0x71726943, 0x6A514306, 0x4B14AD00, 0x64D20D3F, 0x9F37DB15
int main()
{
    int i;
    unsigned int key[4]={0x6B696C69,0x79645F65,0x696D616E,0x67626463};
    unsigned int code[8]={0x5585A199, 0x7E825D68,0x944D0039,0x71726943,0x6A514306,0x4B14AD00,0x64D20D3F,0x9F37DB15};

    for(i=0;i<8;i+=2)
    {
        decrypt(code+i,key);
    }

}
//MRCTF{Dyn4m1c_d3buG_1s_a_ki11eR}

MR_CheckIN

md5

f5e69f42b7a9a0f1c9edede743a1d27f
//Andr01d

得到MRCTF{Andr01d+xxxx}

part2

是一个异或暂时不知道怎么动调so文件,后来知道了,现在补齐

进行一些环境配置,我用的雷电模拟器
https://usher2008.github.io/2021/03/21/%E5%AE%89%E5%8D%93%E9%80%86%E5%90%91%E8%B8%A9%E5%9D%91%E8%AE%B0%E5%BD%95/#usb%E8%BF%9E%E6%8E%A5

在jeb中打断点ctrl+b

然后在模拟器中打开apk,然后开始连接

然后试值,这里我就直接用flag了,MRCTF{Andr01d_check1n_welc0me_to_MRCTF}

停在断点处

MR_register

是一个Debug Blocker,这个内容和《逆向工程核心原理》的api钩取第一节内容有相似部分

双进程保护,实际上是程序本身作为一个进程或一个调试器,并且在调试模式下运行自身程序。所以这种保护通常就会存在两个进程。
这种程序的技术特点是
1. 无法被调试,因为程序本身也是一个调试器。我们又知道一般情况下一个程序只能被一个调试器所调试,如果他的程序先抢占作为了调试器,那么就无法进行调试。所以解决办法只能是在他的调试器附加之前你先开始调试。
2. 一般来说,为了防止你直接抢占调试来绕过,他还会加一个异常处理函数,程序中原本存在一些不合理的代码或者 INT3 断点,当他的调试器处理的时候会去做一些指定的流程,而你作为调试者,在调试过程中就无法处理那些代码。

这样一个进程里面就有两个进程了。而且父进程应该是作为的调试器,然后通过动调可以发现调试器处理了出题人故意在子进程中设置的3个异常。从而恢复了子进程的真实代码。

通过动调可知,发生了3个异常,以及异常相关位置,也就是context.eip的值

1.一个异常是除0异常,这个异常改变了子函数的最后对比的密文

405020
  for ( i = 374; i >= 0; --i )
    Buffer[i] ^= Buffer[i + 1] ^ i;
  Buffer[375] = 120;

2.第二个是int3异常,这个异常有一个smc的处理,还原了子进程的函数

401E1F
    for ( i = 0; i <= 0x57D; ++i )
      *((_BYTE *)v5 + i) ^= i;

3.第3个也是int3异常,跳过了,异常位置

patch掉相关位置就ok

第一个异常的处理我是将动调后的数据,直接改到了原exe文件的二进制数据的位置。

第二个就直接idapython

//from ida_bytes import *
//patch_byte(0x0040169A, 0x90)
版本1:
#include <idc.idc>

static main(){
    auto addr = 0x401E1F;
    auto i = 0;
    for(i=0;i<0x57E;i++){
        PatchByte(addr + i,Byte(addr + i) ^i);
    }
}
版本2:
import idc
st = 0x401E1f
i = 0
while st <= 0x401E1f+0x57d:
    value = ida_bytes.get_byte(st)
    value ^= (i%256)
    ida_bytes.patch_byte(st, value)
    st += 1
    i += 1
版本3:
import idc
def XorBytes(start, length):
    for i in range(length):
        byte_value = ord(idc.get_bytes(start + i, 1)[0])
        print i, hex(byte_value)
        byte_value = byte_value ^ i
        idc.patch_byte(start + i, byte_value)
XorBytes(0x0000000000401E1F, 0x57D)
版本4:(只适用于ida7.0)
import sys
from idautils import *
from idc import *
import idaapi
if __name__ =="__main__":
    start_addr=0x401E1f
    for i in range(0x57E):
        PatchByte(start_addr+i,Byte(start_addr+i)^i)

然后就去掉一些花指令就可以看代码了

先爆破得到source

#include <stdio.h>

char enc[] = {71, 90, 53, 121, 69, 120, 71, 105, 71, 88, 69, 120, 53, 122, 71, 88, 69, 120, 71, 87, 72, 108, 72, 108, 69, 120, 71, 88, 53, 119, 71, 86, 69, 120, 71, 90, 53, 119, 71, 89, 69, 120, 71, 107, 53, 118, 71, 106, 69, 120, 53, 120, 72, 108, 53, 121, 69, 120, 71, 87, 71, 90, 53, 118, 71, 87, 69, 120, 71, 88, 71, 87, 72, 108, 53, 121, 69, 120, 71, 89, 71, 106, 53, 118, 71, 107, 69, 120, 71, 105, 72, 108, 71, 106, 71, 90, 69, 120, 72, 108, 53, 84, 72, 108, 71, 86, 69, 120, 53, 122, 72, 108, 71, 90, 71, 89, 69, 120, 71, 87, 71, 107, 72, 108, 71, 88, 71, 107, 69, 120, 71, 88, 71, 106, 71, 86, 72, 109, 53, 121, 69, 120, 71, 89, 53, 121, 72, 109, 71, 88, 71, 106, 69, 120, 71, 106, 71, 89, 53, 118, 71, 89, 72, 108, 69, 120, 53, 118, 71, 87, 71, 89, 53, 120, 71, 105, 69, 120, 71, 87, 71, 86, 71, 90, 53, 122, 71, 105, 53, 120, 69, 120, 71, 87, 53, 118, 71, 106, 71, 88, 71, 105, 71, 88, 69, 120, 71, 88, 53, 118, 53, 119, 71, 87, 71, 88, 71, 88, 69, 120, 71, 90, 71, 105, 71, 87, 71, 89, 53, 119, 71, 89, 69, 120, 71, 106, 53, 84, 53, 120, 71, 105, 71, 89, 71, 90, 69, 120, 53, 119, 71, 90, 53, 121, 72, 109, 71, 105, 71, 105, 69, 120, 71, 87, 71, 88, 71, 90, 72, 109, 53, 122, 53, 119, 72, 109, 69, 120, 71, 87, 53, 121, 72, 109, 71, 107, 72, 108, 71, 106, 53, 121, 69, 120, 71, 88, 53, 84, 53, 122, 71, 87, 71, 107, 72, 109, 53, 121, 69, 120, 71, 90, 53, 121, 71, 107, 72, 109, 71, 86, 71, 106, 53, 119, 69, 120, 71, 107, 53, 121, 71, 105, 53, 118, 72, 108, 71, 90, 71, 87, 69, 120, 53, 120, 53, 118, 53, 121, 71, 89, 72, 108, 53, 120, 53, 121, 69, 120, 71, 87, 71, 90, 72, 108, 71, 88, 53, 122, 71, 87, 72, 108, 53, 119, 69, 120};


char table[9][9] = {"ABCDEFGH", "12345678", "0IJKLMNO", "+OPQRStu",
                    "\\vwxyzTU", "abcdefgh", "VWXYZijk", "lmnopqrs"};

int main(void)
{
    int i,num1,num2,j,v25,code1,code2;
    char ch;

    for(i=0;i<sizeof(enc)-1;i+=2)
    {
        for(j=32;j<127;j++) 
        {
            ch=j;
            num1=(ch>>6)&1;
            num2=(ch>>3)&7;
            v25=ch&7;
            code1=table[num1][num2];
            code2=table[num2][v25];
            if(code1==enc[i]&&code2==enc[i+1])
            {
                putchar(ch);
                break;
            }

        }

    }

}
//4d#52#e2#188#2b0#4b3#7a6#c8d#14a1#218d#36a7#5864#8f80#e843#17827#2609d#3d926#63a38#a13c5#104e5c#1a6252#2ab122#4513b3#6fc534#b4d955#1249eb9#1d9786d#2fe179d#4d7906b#7d5a841#cad38cd#1482e18b#

注意上面的enc是1byte,这个和最后的比较部分有关。然后用python将#替换为0x

s='4d#52#e2#188#2b0#4b3#7a6#c8d#14a1#218d#36a7#5864#8f80#e843#17827#2609d#3d926#63a38#a13c5#104e5c#1a6252#2ab122#4513b3#6fc534#b4d955#1249eb9#1d9786d#2fe179d#4d7906b#7d5a841#cad38cd#1482e18b#4d'
print(s.replace('#',',0x'))
//0x4d,0x52,0xe2,0x188,0x2b0,0x4b3,0x7a6,0xc8d,0x14a1,0x218d,0x36a7,0x5864,0x8f80,0xe843,0x17827,0x2609d,0x3d926,0x63a38,0xa13c5,0x104e5c,0x1a6252,0x2ab122,0x4513b3,0x6fc534,0xb4d955,0x1249eb9,0x1d9786d,0x2fe179d,0x4d7906b,0x7d5a841,0xcad38cd,0x1482e18b,0x4d

最后解密

#include <stdio.h>
int main(void)
{
    int i;

    unsigned int enc[]={0x4d,0x52,0xe2,0x188,0x2b0,0x4b3,0x7a6,0xc8d,0x14a1,0x218d,0x36a7,0x5864,0x8f80,0xe843,0x17827,0x2609d,0x3d926,0x63a38,0xa13c5,0x104e5c,0x1a6252,0x2ab122,0x4513b3,0x6fc534,0xb4d955,0x1249eb9,0x1d9786d,0x2fe179d,0x4d7906b,0x7d5a841,0xcad38cd,0x1482e18b,0x4d};
    char flag[50];

    flag[0]=0x4d;
    flag[1]=0x52;
    for(i=2;i<100;i++)
    {
        flag[i]=enc[i]-enc[i-1]-enc[i-2];
    }
    puts(flag);
}
//MRCTF{C4n_y0u_d3bug_1t?_n0_wa9!}

ezgame

用ce来分析相关过关条件的地址

星星:xxxxxxxxx3E40  4byte
key:xxxxxxxxx3E48   8byte
door,cookie,alien:xxxxxxxxxx3E68  4个char,01代表true
death:xxxxxxxxxx3E6C 4byte

直接改星星数被cheat,原因是每吃一个星星,key就会发生变换,所以关键就是要知道key是怎么变的。

dump出来,找到位置,c写出来的key变换过程

#include<stdio.h>

__int64 key = 0xDEADBEEFAA114514;

int encode()
{
    int i,j;
    __int64 v10,v12;
    char v13;
    unsigned __int64 v14;

    for(i=0;i<4;i++)
    {
        v10=0;
        v12=1;
        for(j=0;j<64;j++)
        {
            v13 = j & 0x3f;
            v14 = v12 & key;
            v12 = (v12<<1)|(v12>>63);
            v10 ^= v14>>v13;
        }
        key=v10 | 2 * key;
    }    
}

int main()
{
    int i;

    for(i=0;i<105;i++)
    {
        encode();
    }
    printf("0x%llX", key);

}
//0xEA8451453BD5B7DD

然后再去改数据即可得到MRCTF{Ez_G@mE_MaY_Be_Ha3d_4_y0U}