TOC

碎碎念

上周末的RCTF,自闭依旧,不过比De1CTF好一点,一共做了三道,跟学弟一起,依旧是wtclwtclwtcl。浪了两天,补上writeup,这次只写了做出来的三道题。剩下的除了rust-flag,看起来都超过了能力范畴…慢慢补上知识点。

go-flag

首先用IDAGolangHelper恢复符号
恢复符号以后可以看到一共生成了3k多个goroutine,main_main_func1用来获取输入,每次读入一个字符,然后通过chan传给其他的rountine,发送字符到chan使用了runtime_chansend1, 从chan读取字符使用的是runtime_chanrecv1函数,x查找一下调用了runtime_chanrecv1函数的地方,这些函数的个数差不多就是flag的长度。
选择一个调用runtime_chanrecv1的函数进行调试,发现距离这个函数不远的地方有字符判断操作

然后调试到这个地方发现前几次出现的字符分别为RCF猜测就是正确flag,然后找到所有这种比较的函数把字符抄下来就行了。

cipher

MIPS的程序用ghidra反编译可以看到加密逻辑,逆一下就可以了,注意端序和结束符问题。

#include<cstdio>  
#define ulonglong unsigned long long   
#define longlong long long  
using namespace std;  
void encrypt(char *ciphertext,char *plain)  
{  
ulonglong p1,p2;  
ulonglong *in_a2;  
int cycle;  
ulonglong t1,t2,c1,c2;  
p1 = *(ulonglong *)plain;  
p2 = *(ulonglong *)(plain + 8);  
//printf("P1 %llX P2 %llX\n",p1,p2);  
t2 = 0;  
t1 = 0;  
c2 = ((p2>> 8) + (p2<< 0x38) + p1) ^ t2;  
c1 = ((p1 >> 0x3d) + (p1 << 3)) ^ c2;  
cycle = 0;  
while (cycle < 0x1f) {  
t1 = ((t1 >> 8) + (t1 << 0x38) + t2) ^ (longlong)cycle;  
t2 = ((t2 >> 0x3d) + (t2 << 3)) ^ t1;  
//printf("%llX %llX %llX\n",c1,c2,t2);  
c2 = ((c2 >> 8) + (c2 << 0x38) + c1) ^ t2;  
c1 = ((c1 >> 0x3d) + (c1 << 3)) ^ c2;  
cycle = cycle + 1;  
}  
printf("%llX %llX %llX %llX\n",c1,c2,t1,t2);  
*(ulonglong *)ciphertext = c1;  
*(ulonglong *)(ciphertext + 8) = c2;  
  
return;  
}  
ulonglong t1s[40],t2s[40];  
void genFlows(ulonglong k1,ulonglong k2)  
{  
	ulonglong t2 = k2,t1 = k1,cycle = 0;  
	while (cycle < 0x1f) {  
	t1 = (t1 >> 8) + (t1 << 0x38) + t2 ^ (longlong)cycle;  
	t2 = ((t2 >> 0x3d) + (t2 << 3)) ^ t1;  
	t1s[cycle]=t1;  
	t2s[cycle]=t2;  
	cycle+=1;  
	//printf("%d\n",cycle);  
	}  
//	printf("Get Key Flows\n");  
}  
void decrypt(ulonglong k1,ulonglong k2,char *ciphertext,char *plain)  
{  
	genFlows(k1,k2);  
	ulonglong c1,c2;  
	c1 = *(ulonglong *)ciphertext;  
c2 = *(ulonglong *)(ciphertext + 8);  
	longlong cycle = 0x1f;  
	while (cycle > 0) {  
	/*c2 = (c2 >> 8) + (c2 << 0x38) + c1 ^ t2s[cycle];  
	c1 = ((c1 >> 0x3d) + (c1 << 3)) ^ c2;*/  
	cycle = cycle - 1;  
	c1 ^= c2;  
	c1 = ((c1 << 0x3d) + (c1 >> 3));  
	c2 ^= t2s[cycle];  
	c2 -= c1;  
	c2 = (c2 << 8) + (c2 >> 0x38);  
	/*t1 = ((t1 >> 8) + (t1 << 0x38) + t2) ^ (longlong)cycle;  
	t2 = ((t2 >> 0x3d) + (t2 << 3)) ^ t1;*/  
	  
	  
	  
	}  
	//c2 = (p2>> 8) + (p2<< 0x38) + p1 ^ t2;  
	//c1 = (p1 >> 0x3d) + (p1 << 3) ^ c2;  
	c1 ^= c2;  
	c1 = ((c1 << 0x3d) + (c1 >> 3));  
	c2 ^= k2;  
	c2 -= c1;  
c2 = (c2 << 8) + (c2 >> 0x38);  
*(ulonglong *)plain = c1;  
*(ulonglong *)(plain + 8) = c2;  
}  
  
unsigned char cipherText[100]{  
0xc1,0x77,0x1d,0xe1,0x2b,0xf8,0x00,0x2a,0xf4,0x91,0xd5,0x23,0xfc,0x71,0xb1,0xc3,  
//0x57,0x59,0x88,0xc2,0x8b,0x1e,0xf1,0x30,0x75,0xeb,0x2f,0x42,0x77,0xab,0x94,0xd5  
//0xb9,0x98,0x6e,0x46,0xf0,0x76,0x5d,0xe1,0xf2,0x36,0x77,0x5d,0xb5,0xfd,0x51,0xb6  
};  
  
char dePlain[100]={0};  
int main()  
{	  
	for(ulonglong i=0;i<=0xFFFF;i++)  
	{  
		ulonglong k1=0,k2=(i<<48);  
		decrypt(k1,k2,(char*)cipherText,dePlain);  
		for(int i=0;i<16;i++)  
		{  
			printf("%s\n",dePlain);  
		}  
			  
	}  
	  
return 0;  
}  

play_the_game

get flag的部分在libcalculate.so里面,so文件被平坦化了,本来想用angr去一下平坦化看看,但是发现好像不行。
flag是dword_2B00C的md5值,这个值只在sub_76B0中被修改过,调试起来发现只有下棋赢了的时候这个值才会改变,然后只有当dword_2B008的值大于等于0x13f4f9f9的时候才会printlog出flag,因为这两个值只在sub76B0中被修改过了,所以直接dump出这个函数输出dword_2B008输出大于等于0x13f4f9f9时dword_2B00C的值即可。

#include<math.h>  
#include<stdio.h>  
int dword_2B008 = 0x13F4E6A3;  
int dword_2B00C = 0xDEF984B1;  
int sub_76B0()  
{  
signed int v0; // r1  
char v1; // r2  
signed int v2; // r1  
signed int v3; // r12  
signed int v4; // lr  
signed int v5; // r1  
signed int v6; // r2  
signed int v7; // r3  
signed int v8; // r1  
char v9; // r2  
signed int v10; // r1  
signed int v11; // r12  
signed int v12; // lr  
signed int v13; // r1  
signed int v14; // r2  
signed int v15; // r3  
signed int v16; // r1  
signed int v17; // r12  
signed int v18; // lr  
signed int v19; // r1  
char v20; // lr  
signed int v21; // r2  
signed int v22; // r3  
signed int v23; // r1  
signed int v24; // r1  
signed int v25; // r12  
signed int v26; // lr  
signed int v27; // r1  
char v28; // lr  
signed int v29; // r2  
signed int v30; // r3  
signed int v31; // r1  
signed int v32; // r1  
signed int v33; // r12  
signed int v34; // lr  
signed int v35; // r1  
signed int v36; // r2  
signed int v37; // r3  
signed int v38; // r1  
signed int v39; // r2  
signed int v40; // r3  
signed int v41; // r1  
signed int v42; // r12  
signed int v43; // lr  
signed int v44; // r1  
signed int v45; // r12  
signed int v46; // lr  
signed int v47; // r1  
signed int v48; // r2  
signed int v49; // r3  
signed int v50; // r1  
signed int v51; // r2  
signed int v52; // r3  
signed int v53; // r1  
signed int v54; // r2  
signed int v55; // r3  
signed int v57; // [sp+14h] [bp-7Ch]  
int v58; // [sp+18h] [bp-78h]  
signed int v59; // [sp+6Ch] [bp-24h]  
char v60; // [sp+76h] [bp-1Ah]  
char v61; // [sp+77h] [bp-19h]  
  
v59 = (signed int)((sqrt((double)(8 * (dword_2B008 - 0x13F4E6A3) + 1)) - 1.0) / 2.0 + 1.0);  
dword_2B008 += v59;  
v58 = dword_2B008 % 4;  
v57 = 329878480;  
while ( 1 )  
{  
while ( 1 )  
{  
  while ( 1 )  
  {  
    while ( 1 )  
    {  
      while ( 1 )  
      {  
        while ( 1 )  
        {  
          while ( 1 )  
          {  
            while ( 1 )  
            {  
              while ( 1 )  
              {  
                while ( 1 )  
                {  
                  while ( 1 )  
                  {  
                    while ( 1 )  
                    {  
                      while ( 1 )  
                      {  
                        while ( 1 )  
                        {  
                          while ( v57 == -1902481392 )  
                          {  
                            v2 = 982494985;  
                            v3 = 0;  
                            v3 = 1;  
                            v4 = 0;  
                            v4 = 1;  
                            if ( (v3 & 1 ^ v4 & 1 | ~(~v3 | ~v4) & 1) & 1 )  
                              v2 = 631845012;  
                            v57 = v2;  
                          }  
                          if ( v57 != -1839432635 )  
                            break;  
                          v31 = -662380450;  
                          if ( v61 & 1 )  
                            v31 = -356495000;  
                          v57 = v31;  
                        }  
                        if ( v57 != -1690025818 )  
                          break;  
                        v57 = 972960622;  
                      }  
                      if ( v57 != -1673856231 )  
                        break;  
                      v57 = 1037163223;  
                    }  
                    if ( v57 != -1492608071 )  
                      break;  
                    v57 = 973492237;  
                  }  
                  if ( v57 != -1424285714 )  
                    break;  
                  v57 = -662380450;  
                }  
                if ( v57 != -1252652544 )  
                  break;  
                v38 = 834798273;  
                v39 = 0;  
                v39 = 1;  
                v40 = 0;  
                v40 = 1;  
                if ( (v39 & v40 | v39 ^ v40) & 1 )  
                  v38 = 1385700430;  
                v57 = v38;  
              }  
              if ( v57 != -1086664836 )  
                break;  
              v13 = 1181698316;  
              dword_2B00C *= v59;  
              v14 = 0;  
              v14 = 1;  
              v15 = 0;  
              v15 = 1;  
              if ( (v14 & v15 | v14 ^ v15) & 1 )  
                v13 = -854969644;  
              v57 = v13;  
            }  
            if ( v57 != -981935185 )  
              break;  
            dword_2B00C <<= v59 % 8;  
            v57 = -1252652544;  
          }  
          if ( v57 != -854969644 )  
            break;  
          v57 = 2074254629;  
        }  
        if ( v57 != -744507517 )  
          break;  
        v35 = -435027630;  
        dword_2B00C += dword_2B008;  
        v36 = 0;  
        v36 = 1;  
        v37 = 0;  
        v37 = 1;  
        if ( (v36 & v37 | v36 ^ v37) & 1 )  
          v35 = -1424285714;  
        v57 = v35;  
      }  
      if ( v57 != -662380450 )  
        break;  
      v57 = -1252652544;  
    }  
    if ( v57 != -435027630 )  
      break;  
    dword_2B00C += dword_2B008;  
    v57 = -744507517;  
  }  
  if ( v57 != -356495000 )  
    break;  
  v32 = -435027630;  
  v33 = 0;  
  v33 = 1;  
  v34 = 0;  
  v34 = 1;  
  if ( (~v33 ^ ~v34 | ~(~v33 | ~v34) & 1) & 1 )  
    v32 = -744507517;  
  v57 = v32;  
}  
if ( v57 == -7797833 )  
  break;  
switch ( v57 )  
{  
  case 187395956:  
    v10 = 1181698316;  
    v11 = 0;  
    v11 = 1;  
    v12 = 0;  
    v12 = 1;  
    if ( (v11 & 1 ^ v12 & 1 | ~(~v11 | ~v12) & 1) & 1 )  
      v10 = -1086664836;  
    v57 = v10;  
    break;  
  case 329878480:  
    v0 = 564872742;  
    v1 = 0;  
    if ( !(dword_2B008 % 4) )  
      v1 = 1;  
    if ( v1 & 1 )  
      v0 = -1902481392;  
    v57 = v0;  
    break;  
  case 413793462:  
    v57 = 973492237;  
    break;  
  case 475330195:  
    v57 = 1549997554;  
    break;  
  case 564872742:  
    v8 = 963397217;  
    v9 = 0;  
    if ( v58 == 1 )  
      v9 = 1;  
    if ( v9 & 1 )  
      v8 = 187395956;  
    v57 = v8;  
    break;  
  case 631845012:  
    v5 = 982494985;  
    dword_2B00C = (~dword_2B00C & 0x384FD424 | dword_2B00C & 0xC7B02BDB) ^ (~dword_2B008 & 0x384FD424 | dword_2B008 & 0xC7B02BDB);  
    v6 = 0;  
    v6 = 1;  
    v7 = 0;  
    v7 = 1;  
    if ( (v6 & v7 | v6 ^ v7) & 1 )  
      v5 = 413793462;  
    v57 = v5;  
    break;  
  case 792701847:  
    v23 = 851733706;  
    if ( v60 & 1 )  
      v23 = -981935185;  
    v57 = v23;  
    break;  
  case 834798273:  
    v57 = 1385700430;  
    break;  
  case 851733706:  
    v24 = 475330195;  
    v25 = 0;  
    v25 = 1;  
    v26 = 0;  
    v26 = 1;  
    if ( (v25 & 1 ^ v26 & 1 | ~(~v25 | ~v26) & 1) & 1 )  
      v24 = 1549997554;  
    v57 = v24;  
    break;  
  case 963397217:  
    v16 = -1690025818;  
    v17 = 0;  
    v17 = 1;  
    v18 = 0;  
    v18 = 1;  
    if ( (~v17 ^ ~v18 | ~(~v17 | ~v18) & 1) & 1 )  
      v16 = 972960622;  
    v57 = v16;  
    break;  
  case 972960622:  
    v19 = -1690025818;  
    v20 = 0;  
    if ( v58 == 2 )  
      v20 = 1;  
    v60 = v20 & 1;  
    v21 = 0;  
    v21 = 1;  
    v22 = 0;  
    v22 = 1;  
    if ( (v21 & v22 | v21 ^ v22) & 1 )  
      v19 = 792701847;  
    v57 = v19;  
    break;  
  case 973492237:  
    v50 = 1946369812;  
    v51 = 0;  
    v51 = 1;  
    v52 = 0;  
    v52 = 1;  
    if ( (v51 & v52 | v51 ^ v52) & 1 )  
      v50 = 2087024114;  
    v57 = v50;  
    break;  
  case 982494985:  
    dword_2B00C = dword_2B008 & ~dword_2B00C | dword_2B00C & ~dword_2B008;  
    v57 = 631845012;  
    break;  
  case 1037163223:  
    v47 = -1673856231;  
    v48 = 0;  
    v48 = 1;  
    v49 = 0;  
    v49 = 1;  
    if ( (v48 & v49 | v48 ^ v49) & 1 )  
      v47 = -1492608071;  
    v57 = v47;  
    break;  
  case 1181698316:  
    dword_2B00C *= v59;  
    v57 = -1086664836;  
    break;  
  case 1385700430:  
    v41 = 834798273;  
    v42 = 0;  
    v42 = 1;  
    v43 = 0;  
    v43 = 1;  
    if ( (~v42 ^ ~v43 | ~(~v42 | ~v43) & 1) & 1 )  
      v41 = 1848868637;  
    v57 = v41;  
    break;  
  case 1549997554:  
    v27 = 475330195;  
    v28 = 0;  
    if ( v58 == 3 )  
      v28 = 1;  
    v61 = v28 & 1;  
    v29 = 0;  
    v29 = 1;  
    v30 = 0;  
    v30 = 1;  
    if ( (v29 & v30 | v29 ^ v30) & 1 )  
      v27 = -1839432635;  
    v57 = v27;  
    break;  
  case 1848868637:  
    v57 = 2074254629;  
    break;  
  case 1946369812:  
    v57 = 2087024114;  
    break;  
  case 2074254629:  
    v44 = -1673856231;  
    v45 = 0;  
    v45 = 1;  
    v46 = 0;  
    v46 = 1;  
    if ( (v45 & 1 ^ v46 & 1 | ~(~v45 | ~v46) & 1) & 1 )  
      v44 = 1037163223;  
    v57 = v44;  
    break;  
  case 2087024114:  
    v53 = 1946369812;  
    v54 = 0;  
    v54 = 1;  
    v55 = 0;  
    v55 = 1;  
    if ( (v54 & v55 | v54 ^ v55) & 1 )  
      v53 = -7797833;  
    v57 = v53;  
    break;  
}  
}  
return 0;  
}  
int main()  
{  
while(dword_2B008 <= 0x13f4f9f8)  
    sub_76B0();  
printf("%x %x\n", dword_2B008, dword_2B00C);  
// 13f4f9f9 38fa7a28  
return 0;  
}