首页
论坛
课程
招聘
[原创]看雪 2018CTF 第7题 wp
2018-6-30 17:33 1409

[原创]看雪 2018CTF 第7题 wp

2018-6-30 17:33
1409
先看整体结构

    

这道题的整体结构很简单,输入16字节,转成数字,以此数据计算下一轮数据,得到结果再进行下一轮
每轮取3个数字组成 A * 40H * 40H   + B*40H + C ,用这个数据查很大的表

输入--->第一轮结果---->第二轮结果---->....... 最终结果
这类题显然方法是两种
1.正向循环 (因为表很大,这种计算要很多时间)
2.反向逐一计算(选用这种计算速度快)

       使用方法2,就一定要保证数据表是有规律的,单位内无重复
       首先看个位   0x00 - 0x40

第1个40H是无重复的,写工具查看,验证后面每个40H都是无重复的
   即在单位范围内,0-3F内,没有相同的值
   同理再看十位,百位,都是无重复的,这样逆向表法就是可能的了




------------------------
先看他的计算规则吧,输入bcdefghijklmnopq 
这样转换完之后会是 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10,方便看每次取了哪些数据计算了
第一轮:
第一个字节处理后
第二个字节

第三个字节

...一共16个字节都记录下来
----------
先当自己是最后一次计算吧,有如下关系
记录下来的        最终结果
01 02 03        14   
04 05 01        22
06 07 01        1E
06 08 02        10
05 07 02        38
09 03 04        30
0A 03 05        18
08 0B 04        10
09 0D 06        04
0C 0E 07        1A
0D 0E 08        24
0C 0F 0A        08
0F 09 0B        02
10 0A 0B        26
10 0C 0D        38
10 0E 0F        2A

T[0x1000 * a1 + 0x40 * a2 + a3] =  b1 //a1表示第1个输入,b1表示第1个输出
T[0x1000 * a4 + 0x40 * a5 + a1 ] = b2
T[0x1000 * a6 + 0x40 * a6 + a1 ] = b3
...
T[0x1000 * a10 + 0x40 * ae + af ] = b0  

这里有16个未知数要求 a1-a10,   已知 b1-b10

//解这种方程组,给定几个数值后再计算就会很简单
//我选定 第 01 02 04 08 几个数据当成已知数,就可以推测其他数据 ,只要可推,这样就在短时间内跑出来
   对照下面的求解方法看
用for循环给定几个值,[]括号内是用来验证的

以个位做逆向表,百位十位做查询表,就有
  哪张表 : 查询表[百位*十位]
 
// 求逆向表
bool calcReverseTable(byte table1[],byte table2[])
{
	for(int i = 0 ; i < 0x40; i++){	//不能有相同的
		for(int j = i + 1; j < 0x40; j++){
			if(table1[i] == table1[j])
				return false;
		}
	}
	memset(table2,0,0x40);
	for(i = 0 ; i < 0x40; i++){
		table2[table1[i]] = i;
	}
	return true;
}
	//1.做个C逆向表(40H字节) * 40H组
	//2.做个AB表 40H*40H 用AB找到哪个组,直接查
	tableCx = new BYTE[0x40 * 0x40];
	teamAB  = new BYTE[0x40 * 0x40];
	tableBx = new BYTE[0x40 * 0x40];
	teamAC  = new BYTE[0x40 * 0x40];
	tableAx = new BYTE[0x40 * 0x40];
	teamCB  = new BYTE[0x40 * 0x40];
	CreateTable(p,tableCx,teamAB);  
	//个位十位互换做成p2
	//同上
	PBYTE pAC = new BYTE[0x40000];//bc交换     十位个位交换
	for(int i = 0; i < 0x40000; i+= 0x1000)
	{
		for(int j = 0 ; j < 0x40; j++)
		{
			for(int j2 = 0; j2 < 0x40; j2++)
			{
				pAC[i + j * 0x40 + j2] = p[i + j + j2 * 0x40];
			}
		}
	}
	CreateTable(pAC,tableBx,teamAC);
	PBYTE pCB = new BYTE[0x40000];//ac交换   百位个位交换
	for(i = 0; i < 0x40; i++)
	{
		for(int j = 0 ; j < 0x40; j++)
		{
			for(int j2 = 0; j2 <0x40; j2++)
			{
				pCB[i * 0x1000 + j * 0x40 + j2] = p[i + j * 0x40 + j2 * 0x1000];
			}
		}
	}
	CreateTable(pCB,tableAx,teamCB);
//这里3对表
第1对直接生成
第2对,十位,个位互换在生成表
第3对,十位,个位互换在生成表
-------------这样两次查表就能查到结果,第一次查表是查找那个反向表,第二次就是查结果


//利用两个数计算第三个数
//利用2个数查询第三个数
BYTE calcA(BYTE B,BYTE C,BYTE ret)
{
	BYTE tb = teamCB[C * 0x40 + B];
    BYTE k2 = tableAx[tb * 0x40 + ret];
	return k2;
}

BYTE calcB(BYTE A,BYTE C,BYTE ret)
{
	BYTE tb = teamAC[A * 0x40 + C];
    BYTE k2 = tableBx[tb * 0x40 + ret];
	return k2;
}

BYTE calcC(BYTE A,BYTE B,BYTE ret)
{
	//找逆向表C		逆向表(a,b)[ret]	//已经生成了
	//	每40一组,标记0-3F生成  表AB-逆向C
	//1找表
	BYTE tb = teamAB[A * 0x40 + B];
    BYTE k2 = tableCx[tb * 0x40 + ret];
	return k2;
}

//求解方法
bool calcXX(PBYTE pin,PBYTE pout)
{
	BYTE x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc,xd,xe,xf,x0;
	BYTE x7x,xex,xcx,xfx;

	for(x1 = 0; x1 < 0x40; x1++) //用循环爆破 最大次数 40H*40H*40H*40H =  100 0000 次
	{
		for(x2 = 0; x2 < 0x40; x2++)
		{
			for(x4 = 0; x4 < 0x40; x4++)
			{
				for(x8 = 0; x8 < 0x40; x8++)
				{
					//第一步
					x3 = calcC(x1,x2,pin[0]);//14
					x5 = calcB(x4,x1,pin[1]);//22
					x6 = calcA(x8,x2,pin[3]);//10
					xb = calcB(x8,x4,pin[7]);//10
					
					//第二步
					x7 = calcB(x6,x1,pin[2]);//1e
					x7x= calcB(x5,x2,pin[4]);//38
					if(x7 != x7x)
						break;
					x9 = calcA(x3,x4,pin[5]);//30
					xa = calcA(x3,x5,pin[6]);//18
					
					//第三步
					xd = calcB(x9,x6,pin[8]);//04
					xf = calcA(x9,xb,pin[12]);//02
					x0 = calcA(xa,xb,pin[13]);//26
					
					//第四步
					xe = calcB(xd,x8,pin[10]);//24
					xc = calcB(x0,xd,pin[14]);//38
					xex = calcB(x0,xf,pin[15]);//2a
					if(xe != xex)
						break;
					
					//
					xcx= calcA(xe,x7,pin[9]);//1a
					xfx= calcB(xc,xa,pin[11]);//08
					if(xc!=xcx)
						break;
					if(xf!=xfx)
						break;
					
					pout[0] = x1;
					pout[1] = x2;
					pout[2] = x3;
					pout[3] = x4;
					pout[4] = x5;
					pout[5] = x6;
					pout[6] = x7;
					pout[7] = x8;
					pout[8] = x9;
					pout[9] = xa;
					pout[10] = xb;
					pout[11] = xc;
					pout[12] = xd;
					pout[13] = xe;					
					pout[14] = xf;						
					pout[15] = x0;					
												
					return true;
				}
			}
		}	
	}
	return false;
}
//具体见源码


输出结果:
 
14 22 1e 10 38 30 18 10 04 1a 24 08 02 26 38 2a   // 最后1轮    结果
0f 0b 07 0b 35 03 19 1f 0b 31 3b 33 03 07 15 37     // 倒数第2轮
3a 26 00 3a 34 06 2c 3c 0e 1e 0a 26 24 18 3c 18   // 倒数第3轮
0f 07 0d 15 23 3f 3f 19 11 0d 03 25 37 3b 19 31
0c 36 16 06 06 26 04 2e 0c 0c 3a 10 10 16 36 22
0f 1f 33 0d 2b 2b 19 19 3f 33 35 2d 27 1b 11 07
3a 12 3c 0e 2c 3c 2e 08 1e 22 3c 12 26 18 0e 0e
19 2f 03 29 15 03 11 29 15 3f 33 09 1f 1d 23 33
38 1e 38 2a 0e 16 1e 2a 16 2c 1a 1e 3e 10 08 28
27 3d 25 3f 2d 29 19 21 27 39 33 05 17 13 0d 15
30 1c 28 22 24 08 22 10 00 16 10 24 0c 1c 1c 06
25 05 1f 2d 27 33 19 0b 01 0d 21 31 15 31 3b 17
16 2e 36 10 08 28 02 20 06 00 28 0e 14 0a 04 22
35 2d 31 17 3b 1d 29 03 21 0b 0b 3f 05 31 11 1d
3e 0a 2a 02 2a 08 24 1e 1e 3a 38 1e 2c 2a 1c 3c
13 01 27 39 2f 25 1b 09 2d 13 11 1d 31 0b 37 17
2e 22 24 0e 2a 36 00 0e 34 2a 32 00 14 20 14 08
21 1f 17 03 27 2b 29 01 15 1f 1b 05 25 39 35 23
20 30 32 16 32 12 06 32 3c 1a 16 18 30 22 24 1e  //第1轮
11 2b 21 05 3f 01 25 0b 39 13 33 09 3f 39 35 25   //输入

把 11 2b 21 05 3f 01 25 0b 39 13 33 09 3f 39 35 25 
   转成字符串  rPFf9bJl3tXj93ZJ



看雪侠者千人榜,看看你上榜了吗?

最后于 2018-6-30 17:38 被瞧红尘编辑 ,原因:
上传的附件:
收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回