-
-
[原创] CTF签到题
-
发表于: 2021-5-11 10:51 2328
-
签到题 拜师学艺
定位到Main函数
发现sub_401470这个函数是对后面的代码进行解密,执行完sub_401470这个函数后,将程序dump下来,我们就可以在IDA中F5看伪代码了
查看IDA伪代码
阅读上面代码我们知道Flag的长度为0xC, 形式为flag(xxx), 很明显sub_401050就是关键函数,我们来看下这个函数的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | unsigned char byte_403188[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ; unsigned char szDstBuf[ 10000 ] = {}; unsigned char * sub_401050(unsigned char * szFlag, int nFlagLen) { int v3; / / edi int v4; / / edx unsigned int v5; / / esi int v7; / / eax int nSum; / / edi char v9; / / al int v10; / / edi unsigned char * v11; / / [esp + Ch] [ebp - 4h ] v11 = szFlag; v3 = 0 ; v4 = 0 ; v5 = 0 ; if (!szFlag) { return 0 ; } for ( int i = 0 ; i < nFlagLen; i + + ) { if (v5 > = 8187 ) { break ; } v7 = * szFlag; + + v4; + + szFlag; nSum = v7 + v3; if (v4 = = 3 ) { szDstBuf[v5] = byte_403188[nSum >> 18 ]; szDstBuf[v5 + 1 ] = byte_403188[(nSum >> 12 ) & 0x3F ]; szDstBuf[v5 + 2 ] = byte_403188[(nSum >> 6 ) & 0x3F ]; szDstBuf[v5 + 3 ] = byte_403188[nSum & 0x3F ]; v3 = 0 ; v4 = 0 ; v5 + = 4 ; } else { v3 = nSum << 8 ; } } szDstBuf[v5] = 0 ; return szDstBuf; } |
这个算法很简单,就是把我们输入的Flag分成3个字母为一组,将这3个字母进行移位相加存到nSum这个变量中,最后对nSum进行4次计算,得到4个下标值, 去byte_403188数组中取出4个字母.
Flag的长度为0xC, 3个字母一组,分为4组,每组可以在byte_403188数组中取出4个字母,最后将每组取出的字母进行拼接,若计算出来的字符串为"ZmxhZ3trYW54dWV9", 则说明Flag有效
假如我们输入的Flag为 flag{LuoHun}
fla | g{L | uoH | un} | |
---|---|---|---|---|
对应的十六进制 | 0x66 0x6C 0x61 | 0x67 0x7B 0x4C | 0x75 0x6F 0x48 | 0x75 0x6E 0x7D |
nSum | 0x666c61 | 0x677B4C | 0x756F48 | 0x756E7D |
nSum >> 18 | 0x19 | 0x19 | 0x1d | 0x1d |
nSum >> 12) & 0x3F | 0x26 | 0x37 | 0x16 | 0x16 |
(nSum >> 6) & 0x3F | 0x31 | 0x2d | 0x3d | 0x39 |
nSum & 0x3F | 0x21 | 0xc | 0x8 | 0x3d |
最后在byte_403188数组中取出的字符串为"ZmxhZ3tMdW9IdW59"
逆运算代码
知道了正向计算过程,我们来逆向计算下Flag吧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | #include <stdlib.h> #include <stdio.h> #include <string.h> #include <windows.h> #define BYTEn(x, n) (*((BYTE*)&(x)+n)) #define BYTE1(x) BYTEn(x, 1) #define BYTE2(x) BYTEn(x, 2) unsigned char byte_403188[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ; void SortFindIndex( int nCurrentIndex, char * szFind, int nFindLen, int * szFindIndex) { for ( int i = 0 ; i < nFindLen; i + + ) { if (byte_403188[nCurrentIndex] = = szFind[i]) { szFindIndex[i] = nCurrentIndex; } } } void LuoFind(char * szFind, int * szFindIndex, int nFindLen) { int nSize = sizeof(byte_403188); int nCount = 0 ; for ( int i = 0 ; i < nSize; i + + ) { if (byte_403188[i] = = szFind[ 0 ] || byte_403188[i] = = szFind[ 1 ] || byte_403188[i] = = szFind[ 2 ] || byte_403188[i] = = szFind[ 3 ]) { / / 对找到的下标, 按照szFind中的字母顺序进行排序 SortFindIndex(i, szFind, nFindLen, szFindIndex); if ( + + nCount = = nFindLen) { break ; } } } } bool LuoCalcSum( int & nSum, int * szFindIndex) { for (unsigned int i = 1 ; i < 0x99999999 ; i + + ) { if ((i >> 18 ) = = szFindIndex[ 0 ] && ((i >> 12 ) & 0x3F ) = = szFindIndex[ 1 ] && ((i >> 6 ) & 0x3F ) = = szFindIndex[ 2 ] && (i & 0x3F ) = = szFindIndex[ 3 ]) { nSum = i; return true; } } return false; } void PrintFlag( int nSum) { printf( "%c%c%c" , BYTE2(nSum), BYTE1(nSum), nSum); } void LuoCalcFlag(char * szDstCmpStr, int nCmpStrLen) { char * szFind = NULL; int szFindIndex[ 100 ] = {}; int nSum = 0 ; bool nFlag = false; printf( "szFlag: " ); for ( int i = 0 ; i < nCmpStrLen; i + = 4 ) { szFind = &szDstCmpStr[i]; / / 每 4 个字母一组.查找在byte_403188数组中的下标 LuoFind(szFind, szFindIndex, sizeof(szFind)); / / 穷举爆破nSum的值 nFlag = LuoCalcSum(nSum, szFindIndex); if (nFlag = = true) { / / 打印flag PrintFlag(nSum); } } printf( "\r\n" ); } int main() { char szDstCmpStr[] = "ZmxhZ3trYW54dWV9" ; int nCmpStrLen = strlen(szDstCmpStr); / / 计算flag LuoCalcFlag(szDstCmpStr, nCmpStrLen); system( "pause" ); } |
运行上述代码,即可计算出Flag
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2021-5-11 10:52
被夏洛魂编辑
,原因:
赞赏
谁下载
无
看原图
赞赏
雪币:
留言: