当前位置:网站首页>[buuctf.reverse] 114_ [MRCTF2020]VirtualTree

[buuctf.reverse] 114_ [MRCTF2020]VirtualTree

2022-06-09 11:34:00 Shi Shi Shi Shi Shi Shi Shi Shi Shi Shi Shi Shi Shi Shi Shi Shi

This kind of question dares to directly give the original code is also really confident . But it's really difficult if you don't give the source code .

use ida Decompilation found a problem , There is some interference inside E8, This will be changed after transfer ida Yes call . The original code has been explained clearly .

	_asm
	{
		xor eax,eax
		jz label2
		_emit 0xE8
		label2:
	}

Mr. program becomes a binary tree , And assign the node as A-P

int init()
{
	tree *n[16];
	for(int i=0;i<16;i++)
		n[i]=(tree*)malloc(sizeof(tree));
	for(int i=0;i<16;i++)
		n[i]->data='A'+i;
	n[0]->left=n[1];
	n[0]->right=n[2];
	n[1]->left=n[3];
	n[1]->right=n[4];
	n[2]->left=n[5];
	n[2]->right=n[6];
	n[3]->left=n[7];
	n[3]->right=n[8];
	n[4]->left=n[9];
	n[4]->right=NULL;
	n[5]->left=n[10];
	n[5]->right=NULL;
	n[6]->left=n[11];
	n[6]->right=n[12];
	n[7]->right=n[7]->left=NULL;
	n[8]->left=NULL;
	n[8]->right=n[13];
	n[9]->left=n[9]->right=NULL;
	n[10]->left=n[14];
	n[10]->right=n[15];
	n[11]->left=n[11]->right=n[12]->left=n[12]->right=NULL;
	n[13]->left=n[13]->right=NULL;
	n[14]->left=n[14]->right=n[15]->left=n[15]->right=NULL;
	Tree=n[0];
	return 1;
}
int inited=init();

And then I did something replace, Make a little change to the program , The first 1 Segment will point to 401510 fake The value of the function is changed to point to other functions , Other functions are placed in turn list in

void *list[15]={add,xors,add,sub,xors,sub,add,xors,sub,sub,xors,sub,xors,add};

int replace()
{
	void *addr=doit;
	int val=(int)addr;
	DWORD old;
	if(VirtualProtect(addr,512,PAGE_EXECUTE_READWRITE,&old)==NULL)
		exit(0);
	int count=0;
	while(*((PBYTE)val)!=0x90)
	{
		if(*((PDWORD)val)==0x00401510)
			*((PDWORD)val)=(DWORD)list[count++];
		val=val+1;
	}
	addr=main;
	val=(int)addr;
	if(VirtualProtect(addr,512,PAGE_EXECUTE_READWRITE,&old)==NULL)
		exit(0);
	while(*((PBYTE)val)!=0x90)
	{
		if(*((PDWORD)val)==(DWORD)walkB)
		{
			*((PDWORD)val)=(DWORD)walkA;
			break;
		}
		val=val+1;
	}
}

int s=replace();

The second time will be main Inside walkB Change it to walkA

int main()
{
	fake(0,0);
	printf("Give Me Your Key:\n");
	scanf_s("%s",&buff,30);
	if(strlen((char*)buff)!=16)
	{
		printf("Wrong!\n");
		exit(0);
	}
	char flag[20]="";
	memcpy(flag,buff,16);
	_asm push Tree;
	_asm mov eax,walkB;
	_asm call eax;    // walkB(Tree)  right,root,left
	doit();
	_asm nop;
    for(int i=0;i<16;i++)
		if(cmps[i]!=buff[i])
		{
			printf("Wrong!\n");
			exit(0);
		}
	printf("Right!\n");
	printf("your flag: MRCTF{%s}\n",flag);
	system("pause");
	return 0;
}

In this way, the general process is clear .

The program first uses... For the input walkA The first step is to put the right root in the order of the left root buff The root character of the input content in the first XOR .

And then execute doit Encrypt the input , The solution is list In the list

Then with cmps Compare .

The revised and procedures are as follows :

// re_revenge.cpp :  This file contains  "main"  function . Program execution will start and end here .
//

#include <cstdio>
#include <cstdlib>
#include <windows.h>
//@_7r3e_f0r_fuNN!
struct tree
{
	unsigned char data;
	tree *right;
	tree *left;
}*Tree;
unsigned char cmps[]={0x17,0x63,0x77,0x3,0x52,0x2E,0x4A,0x28,0x52,0x1B,0x17,0x12,0x3A,0xA,0x6C,0x62};
unsigned char buff[1000],size=0;
int main();
void walkA(tree *T);
void walkB(tree *T);
void add(int a,int b);
void xors(int a,int b);
void sub(int a,int b);
void* func[5]={NULL};
int init()
{
	tree *n[16];
	for(int i=0;i<16;i++)
		n[i]=(tree*)malloc(sizeof(tree));
	for(int i=0;i<16;i++)
		n[i]->data='A'+i;
	n[0]->left=n[1];
	n[0]->right=n[2];
	n[1]->left=n[3];
	n[1]->right=n[4];
	n[2]->left=n[5];
	n[2]->right=n[6];
	n[3]->left=n[7];
	n[3]->right=n[8];
	n[4]->left=n[9];
	n[4]->right=NULL;
	n[5]->left=n[10];
	n[5]->right=NULL;
	n[6]->left=n[11];
	n[6]->right=n[12];
	n[7]->right=n[7]->left=NULL;
	n[8]->left=NULL;
	n[8]->right=n[13];
	n[9]->left=n[9]->right=NULL;
	n[10]->left=n[14];
	n[10]->right=n[15];
	n[11]->left=n[11]->right=n[12]->left=n[12]->right=NULL;
	n[13]->left=n[13]->right=NULL;
	n[14]->left=n[14]->right=n[15]->left=n[15]->right=NULL;
	Tree=n[0];
	return 1;
}
int inited=init();
void *list[15]={add,xors,add,sub,xors,sub,add,xors,sub,sub,xors,sub,xors,add};
int idx=0;
void xors(int a,int b)
{
	buff[a]=buff[a]^buff[b];
}
void sub(int a,int b)
{
	buff[a]=abs(buff[a]-buff[b]);
}
void add(int a,int b)
{
	buff[a]+=b;
}
void fake(int a,int b)
{
	if(a==0 || b==0)
		return;
	for(int i=0;i<=b;i++)
	{
		buff[i]^=a;
		buff[i]=(buff[i]>>b | buff[i]<<(8-b));
		buff[i]=(1<<(i%8))^buff[i];
		for(int j=1;j<15;j++)
		{
			buff[i]^=buff[j]&0xDF;
		}
			
	}
}	
void walkA(tree *T)
{
	if(T->data!=NULL)
	{
		if(T->right!=NULL)
			walkA(T->right);
		if(T->left!=NULL)
			walkA(T->left);
		buff[idx++]^=T->data;
	}
}
void walkB(tree *T)
{

	if(T->data!=NULL)
	{
		if(T->right!=NULL)
			walkB(T->right);
		buff[idx++]^=T->data;
		if(T->left!=NULL)
			walkB(T->left);
	}
}
void doit();
void doit()
{
	add(0,10);  // stay replace Lieutenant general fake Change it to list The corresponding function in 
	xors(1,2);
	add(2,7);
	sub(3,7);
	xors(4,5);
	sub(6,1);
	add(7,3);
	xors(8,7);
	sub(9,8);
	sub(10,7);
	xors(11,12);
	sub(12,2);
	xors(14,15);
	add(15,2);
}
int replace()      // This function is no longer used 
{
	void *addr=doit;
	int val=(int)addr;
	DWORD old;
	if(VirtualProtect(addr,512,PAGE_EXECUTE_READWRITE,&old)==NULL)
		exit(0);
	int count=0;
	while(*((PBYTE)val)!=0x90)
	{
		if(*((PDWORD)val)==0x00401510)
			*((PDWORD)val)=(DWORD)list[count++];                 // Press list take fake Change to the corresponding function 
		val=val+1;
	}
	addr=main;
	val=(int)addr;
	if(VirtualProtect(addr,512,PAGE_EXECUTE_READWRITE,&old)==NULL)
		exit(0);
	while(*((PBYTE)val)!=0x90)
	{
		if(*((PDWORD)val)==(DWORD)walkB)
		{
			*((PDWORD)val)=(DWORD)walkA;                        // take main Medium walkB Change it to walkA
			break;
		}
		val=val+1;
	}
}

//int s=replace();
int main()
{
	fake(0,0);// It's useless 
	printf("Give Me Your Key:\n");
	scanf_s("%s",&buff,30);
	if(strlen((char*)buff)!=16)
	{
		printf("Wrong!\n");
		exit(0);
	}
	char flag[20]="";
	memcpy(flag,buff,16);
	walkA(Tree);            //replace Lieutenant general walkB Change it to walkA
	// walkA(Tree)  right,left,root buff: MLGPOKFCJENIHDBA  The input values buff Exclusive or 
	doit();
    for(int i=0;i<16;i++)
		if(cmps[i]!=buff[i])
		{
			printf("Wrong!\n");
			exit(0);
		}
	printf("Right!\n");
	printf("your flag: MRCTF{%s}\n",flag);
	system("pause");
	return 0;
}

Write reverse code from back to front in this way ( Draw the tree by hand , only 16 It is faster to manually write characters ):

cmps = [0x17,0x63,0x77,0x3,0x52,0x2E,0x4A,0x28,0x52,0x1B,0x17,0x12,0x3A,0xA,0x6C,0x62]

treexor = b'MLGPOKFCJENIHDBA'
cmps[15]-=2
cmps[14]^= cmps[15]
cmps[12] = cmps[2]- cmps[12]
cmps[11]^= cmps[12]
cmps[10] = cmps[7]- cmps[10]
cmps[9] = cmps[8] - cmps[9]
cmps[8]^= cmps[7]
cmps[7]-=3
cmps[6] = cmps[1]- cmps[6]
cmps[4]^= cmps[5]
cmps[3] = cmps[7]- cmps[3]
cmps[2]-=7
cmps[1]^=cmps[2]
cmps[0]-=10
flag = bytes([cmps[i]^treexor[i] for i in range(16)])
print(flag)
#pctf{s4d_chugg4_n01zez}
#flag{s4d_chugg4_n01zez}

原网站

版权声明
本文为[Shi Shi Shi Shi Shi Shi Shi Shi Shi Shi Shi Shi Shi Shi Shi Shi]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/160/202206091046519039.html