NCTF2019 RE方向部分WP

这次逆向8道只做了5道,说到底还是太菜了
1.签到题
这道题还真就是签到题,只要有IDA就可以看出来是矩阵乘法
将输入的字符串ASCII与矩阵相乘,然后检验结果是否是指定的结果
签到把矩阵提取出来,把最后的对比数据提取出来就可
[12 53 6 34 58 36 1
83 85 12 73 27 96 52
78 53 24 36 86 25 46
39 78 52 9 62 37 84
23 6 14 74 48 12 83
27 85 92 42 48 15 72
4 6 3 67 0 26 68]
最后就是求解其次方程组了,直接上网站去解就可以了
FLAG->NCTF{nctf2019_linear_algebra_is_very_interesting}

2.debug
这道题只是单纯的考察动调
中途生成flag来和输入的字符串比较 只需要再比较的地方下断点,查看栈即可得到答案。
debug调试执行至此,点开s就是flag
在这里插入图片描述

3.F-Bird
16位的小游戏,做的挺精致的
运行的话要DOSBOX,无法动调
直接看汇编,有一段异或,不过用bx寄存器高低位依次异或 算出来两个异或的数是多少 然后异或就行了
f-bird具体怎么计算出两个交替异或的值呢?鉴于告诉了flag以NCTF开头
所以直接拿前两个异或0x8E,0x9D(图中第一,第二个数据)
就可以知道是0xde和0xc0
把那些数据一字节一字节的导出就可以了

k=[0x8E,0x9D,0x94,0x98,0xBB,0x89,0xF3,0xEF,0x83,0xEE,0xAD,0x9B,0x9F,0x9A,0xF0,0xEB,0x9F,0x97,0xF6,0xBC,0xF1,0xE9,0x9F,0xE7,0xA1,0xB3,0xF3,0xA3]
i=0
flag=""
for c in k:
	if(i&1):
		flag=flag+chr(c^0xde)
	else:
		flag=flag+chr(c^0xc0)
	i=i+1
print(flag)

即可得到flag->NCTF{W31C0mE_D05_I6b17_9am3}

4.Easy Ternary
IDA打开发现复杂的一批,发现窗口里有GG字符串,直接去exe里搜索
竟然找到了神秘代码
后面得知是AutoHotKey,exe是个解释器加脚本(怪不得如此复杂)

XOR(a, b)
{
	tempA := a
	tempB := b
	ret := 0
	Loop, 8
	{
		ret += Mod((((tempA >> ((A_Index - 1)*4)) & 15) + ((tempB >> ((A_Index - 1)*4)) & 15)),3) * (16**(A_Index-1))
	}
	return ret
}
InputBox, userInput, TTTTCL, Input your flag:
if(ErrorLevel)
	Exit
if(!StrLen(userInput))   #没有读入
{
	MsgBox, GG
	Exit
}
inputArr := []   #保存输入的数据
Loop, parse, userInput
{
	temp:=A_Index
	inputArr.Push(Ord(A_LoopField))    #读入读入框
}
inputNum := []     #操作后保存的数组
Loop % inputArr.Length()
{
	temp := inputArr[A_Index]     
	temp := DllCall("aiQG.dll\?ToTrit@@YAII@Z", "UInt", temp)
	inputNum.push(temp)       
}
key1 := XOR(inputNum[5], inputNum[inputNum.Length()])   #key就是{}的XOR
inputFlag := []
Loop % inputArr.Length()
{
	temp := XOR(inputNum[A_Index], key1)
	if(Mod(A_Index,2))
	{
		temp := XOR(key1,temp)
	}
	inputFlag.push(temp)
}
temp1 := 1  #是否成功
Loop % inputFlag.Length()     #检验
{
	temp := inputFlag[A_Index]
	temp := DllCall("aiQG.dll\?Check@@YAIII@Z", "UInt", temp, "UInt", A_Index)
	if(!temp)
	{
		temp1 := 0
	}
}
if(temp1)
{
	MsgBox, Ok
}
if(!temp1)
{
	MsgBox, GG
}

并不复杂啊
本质就是输入字符串后转化三进制(DLL里ToTrit),在一波XOR操作一下,最后在check(DLL里Check)一下
XOR操作有一个KEY,可以推算出这个KEY=XOR(ToTrit(’{’),ToTrit(’}’)) ;
有点恶心就是这个三进制是十六进制下看起来的三进制—>0x221120;
根据XOR性质就很容易写出exp,需要注意的是对比的数据是存在DLL里,需要用IDA导出数据

#include<cstdio>
#include<cmath>
#include<windows.h>
using namespace std;
int xors(int a,int b)
{
	int ret=0;
	for(int i=1;i<=8;i++)
		ret=ret+(((a>>(((i-1)*4))&15)+((b>>((i-1)*4))&15))%3)*(pow(16,(i-1)));
	return ret;
} 
int change(int x)
{
	int t,ans=0,k=0;
	while(x)
	{
		t=x%10;
		ans=ans+pow(3,k++)*t;
		x/=10;
	}
	return ans;
}
void genS()
{
	int data[100]={0x00,0x10011,0x21020,0x21101,0x21000,0x22211,0x2220,0x21200,0x2101,0x22120,0x20122,0x22220,0x2021,0x10122,0x20102,0x22111,0x211,0x12012,0x2210,0x22202,0x2021,0x21101,0x2222,0x21101,0x2222,0x21121,0x21120,0x22210};//dll导出数据
	for(int c=1;c<=27;c++)
	{
		for(int i=0;i<=0x22222222;i++)  //暴力枚举2333
		{
			int t=xors(i,0x22212);
			if(c%2)
				t=xors(0x22212,t);
			if(t==data[c])
			{
				printf("%X,",i);
				break;
			}	
		} 	
	}
}
int main()
{
	int s[1000]={2220,2111,10010,2121,11120,10011,10112,10222,11002,1210,11102,10112,2001,1220,11020,11002,1221,10001,11111,10112,10010,10010,10010,10010,10000,2211,11122,0};  //这个是枚举出来的数据,有genS生成,转化为十进制ASCII就是flag
	for(int i=0;s[i]!=0;i++)
		printf("%c",change(s[i]));
    return 0;
}


flag就是NCTF{U_kn0w_73rn4Ry_TTTTQL}

5.丑陋的代码
确实怪丑陋的,各种跳转,根据字符串跳转到关键代码里,发现大体上思路是读入字符串,然后经过一系列操作后和最后的数据进行对比,根据汇编可知flag长度位0x18
ugly但是在动调的时候发现在标红的地方程序结束了,可知有个反调试,于是一层层点进去查看,
在这里插入图片描述有个jmp,明显有问题,于是乎将这个jmp patch掉就发现可执行了,有些看起来乱七八糟的函数也变得可以看了,然后开始头铁,发现字符串输入后前八个字节每四个一组加上了不同的数,最后又来这样操作了一下

unsigned char encode(unsigned char c)
{
	int a=c>>5,b=c<<3;
	return ((a|b)^0x5A);
}

最后还要来个每四个字节奇怪的操作,后面发现是个TEA,在这里IDA并不能识别函数,你需要手动定义,然后发现可以F5,看到0x9e3779b9,显然就是TEA了
这里没有定义函数这里一定要定义下函数,F5,不然难得看
定义函数EXP:

#include<cstdio>
#define _DWORD int
using namespace std;
unsigned char code[]={0x88,0x71,0x3E,0xFE,0x66,0xF6,0x77,0xD7,0xA0,0x51,0x29,0xF9,0x11,0x79,0x71,0x49,0xF1,0x61,0xA0,0x9,0xF1,0x29,0x1,0xB1};
/*
tea_decrypt(0x61869F5E,0x0A9CF08D);
tea_decrypt(0xAD74C0CA,0xA57F16B8);
tea_decrypt(0xB559626D,0xD17B68E0);*/ 
//这里先把基础数据解密
int getlowbit(int x)
{
	return x&0xFF;
}
void tea_decrypt(unsigned long v0,unsigned long v1) 
{     
     unsigned long sum=0xC6EF3720,i; 
     unsigned long delta=0x9e3779b9;                          
     unsigned long k0=0x12345678,k1=0xBADF00D,k2=0x05201314,k3=0x87654321;     //密钥
     for(i=0;i<32;i++) 
     {                               
         v1-=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
         v0-=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
         sum-=delta;                 
     }
	 unsigned char* v=((unsigned char*)&v0);
	 printf("0x%X 0x%X 0x%X 0x%X\n",getlowbit(*((char*)v)),getlowbit(*((char*)v+1)),getlowbit(*((char*)v+2)),getlowbit(*((char*)v+3)));
	 v=((unsigned char*)&v1);
	 printf("0x%X 0x%X 0x%X 0x%X\n",getlowbit(*((char*)v)),getlowbit(*((char*)v+1)),getlowbit(*((char*)v+2)),getlowbit(*((char*)v+3)));
}
unsigned char encode(unsigned char c)
{
	int a=c>>5,b=c<<3;
	return ((a|b)^0x5A);
}
int main()
{
	for(int i=0;i<24;i++)
	{
		int c=code[i];
		for(int j=0;j<=0xFF;j++)//爆枚大法好啊,无脑操作
			if(c==encode(j))
			{
				int t=j;
				if(i==0 || i==4)
					t-=0xC;
				if(i==1 || i==5)
					t-=0x22;
				if(i==2 || i==6)
					t-=0x38;
				if(i==3 || i==7)
					t-=0x4E;
				printf("%c",t);
			}
	}
    return 0;
}

FLAG->NCTF{smc_antidebug_junk}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值