-
-
[原创]看雪.纽盾 KCTF晋级赛2019 Q2 第六题 消失的岛屿
-
发表于: 2019-6-18 14:37 2953
-
用IDA载入文件,提示有DWARF debug information,选择yes,可以看到更多的信息。然后我们找到main函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | int __cdecl main( int argc, const char **argv, const char **envp) { int v3; // eax uint8_t bindata; // [esp+11h] [ebp-3Fh] const char *v6; // [esp+48h] [ebp-8h] char *v7; // [esp+4Ch] [ebp-4h] __main(); printf ( "please enter Serial:" ); scanf ( " %s" , &bindata); if ( strlen (( const char *)&bindata) > 0x31 ) puts ( "error" ); v7 = ( char *) calloc (1u, 0x400u); v3 = strlen (( const char *)&bindata); base64_encode(&bindata, v7, v3); v6 = "!NGV%,$h1f4S3%2P(hkQ94==" ; if ( ! strcmp ( "!NGV%,$h1f4S3%2P(hkQ94==" , v7) ) puts ( "Success" ); else puts ( "Please Try Again" ); free (v7); system ( "pause" ); return 0; } |
这几乎是源代码了,而且代码逻辑也很简单,输入的字符串base64编码以后跟"!NGV%,$h1f4S3%2P(hkQ94=="比较,相同则成功。但是这个看起来不是标准base64编码,进入base64_encode函数看看。
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 | int __cdecl base64_encode( const uint8_t *bindata, char *base64, int binlength) { int v3; // eax char *v4; // ebx int v5; // eax int v6; // ST0C_4 char *v7; // ebx int v8; // eax int v9; // eax char *v10; // ebx int v11; // eax int v12; // eax char *v13; // ebx uint8_t current; // [esp+Bh] [ebp-Dh] uint8_t currenta; // [esp+Bh] [ebp-Dh] int j; // [esp+Ch] [ebp-Ch] int ja; // [esp+Ch] [ebp-Ch] int jb; // [esp+Ch] [ebp-Ch] int i; // [esp+10h] [ebp-8h] i = 0; j = 0; while ( i < binlength ) { v3 = j; ja = j + 1; v4 = &base64[v3]; *v4 = charEncrypt((bindata[i] >> 2) & 0x3F); current = 16 * bindata[i] & 0x30; if ( i + 1 >= binlength ) { v5 = ja; v6 = ja + 1; v7 = &base64[v5]; *v7 = charEncrypt(current); base64[v6] = 61; v8 = v6 + 1; j = v6 + 2; base64[v8] = 61; break ; } v9 = ja; jb = ja + 1; v10 = &base64[v9]; *v10 = charEncrypt((bindata[i + 1] >> 4) | current); currenta = 4 * bindata[i + 1] & 0x3C; if ( i + 2 >= binlength ) { base64[jb] = charEncrypt(currenta); v11 = jb + 1; j = jb + 2; base64[v11] = '=' ; break ; } base64[jb] = charEncrypt((bindata[i + 2] >> 6) | currenta); v12 = jb + 1; j = jb + 2; v13 = &base64[v12]; *v13 = charEncrypt(bindata[i + 2] & 0x3F); i += 3; } base64[j] = 0; return j; } |
charEncrypt函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | char __cdecl charEncrypt( int data) { int dataa; // [esp+18h] [ebp+8h] dataa = aTuvwxtulmnopqr[data]; if ( dataa > '@' && dataa <= 'Z' ) return 0x9B - dataa; if ( dataa > '`' && dataa <= 'z' ) return dataa - 0x40; if ( dataa > '/' && dataa <= '9' ) return dataa + '2' ; if ( dataa == '+' ) return 'w' ; if ( dataa == '/' ) dataa = 'y' ; return dataa; } |
我们可以通过
charEncrypt函数得到真实的码表,把代码复制一份,做点小修改
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 | #include <stdio.h> char b64_chr[] = "tuvwxTUlmnopqrs7YZabcdefghij8yz0123456VWXkABCDEFGHIJKLMNOPQRS9+/" ; char charEncrypt( int data) { int dataa; // [esp+18h] [ebp+8h] dataa = data; if ( dataa > '@' && dataa <= 'Z' ) return 0x9B - dataa; if ( dataa > '`' && dataa <= 'z' ) return dataa - 0x40; if ( dataa > '/' && dataa <= '9' ) return dataa + '2' ; if ( dataa == '+' ) return 'w' ; if ( dataa == '/' ) dataa = 'y' ; return dataa; } int main( int argc, char const *argv[]) { for ( int i = 0; i < sizeof (b64_chr); ++i) { printf ( "%c" ,charEncrypt(b64_chr[i])); } return 0; } |
运行得到"45678GF,-./0123iBA!\"#$%&'()*j9:bcdefghEDC+ZYXWVUTSRQPONMLKJIHkwy",这个就是真正的码表。
用这个码表解密"
!NGV%,$h1f4S3%2P(hkQ94==",得到key:KanXue2019ctf_st
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | int __cdecl main( int argc, const char **argv, const char **envp) { int v3; // eax uint8_t bindata; // [esp+11h] [ebp-3Fh] const char *v6; // [esp+48h] [ebp-8h] char *v7; // [esp+4Ch] [ebp-4h] __main(); printf ( "please enter Serial:" ); scanf ( " %s" , &bindata); if ( strlen (( const char *)&bindata) > 0x31 ) puts ( "error" ); v7 = ( char *) calloc (1u, 0x400u); v3 = strlen (( const char *)&bindata); base64_encode(&bindata, v7, v3); v6 = "!NGV%,$h1f4S3%2P(hkQ94==" ; if ( ! strcmp ( "!NGV%,$h1f4S3%2P(hkQ94==" , v7) ) puts ( "Success" ); else puts ( "Please Try Again" ); free (v7); system ( "pause" ); return 0; } |
这几乎是源代码了,而且代码逻辑也很简单,输入的字符串base64编码以后跟"!NGV%,$h1f4S3%2P(hkQ94=="比较,相同则成功。但是这个看起来不是标准base64编码,进入base64_encode函数看看。
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 | int __cdecl base64_encode( const uint8_t *bindata, char *base64, int binlength) { int v3; // eax char *v4; // ebx int v5; // eax int v6; // ST0C_4 char *v7; // ebx int v8; // eax int v9; // eax char *v10; // ebx int v11; // eax int v12; // eax char *v13; // ebx uint8_t current; // [esp+Bh] [ebp-Dh] uint8_t currenta; // [esp+Bh] [ebp-Dh] int j; // [esp+Ch] [ebp-Ch] int ja; // [esp+Ch] [ebp-Ch] int jb; // [esp+Ch] [ebp-Ch] int i; // [esp+10h] [ebp-8h] i = 0; j = 0; while ( i < binlength ) { v3 = j; ja = j + 1; v4 = &base64[v3]; *v4 = charEncrypt((bindata[i] >> 2) & 0x3F); current = 16 * bindata[i] & 0x30; if ( i + 1 >= binlength ) { v5 = ja; v6 = ja + 1; v7 = &base64[v5]; *v7 = charEncrypt(current); base64[v6] = 61; v8 = v6 + 1; j = v6 + 2; base64[v8] = 61; break ; } v9 = ja; jb = ja + 1; v10 = &base64[v9]; *v10 = charEncrypt((bindata[i + 1] >> 4) | current); currenta = 4 * bindata[i + 1] & 0x3C; if ( i + 2 >= binlength ) { base64[jb] = charEncrypt(currenta); v11 = jb + 1; j = jb + 2; base64[v11] = '=' ; break ; } base64[jb] = charEncrypt((bindata[i + 2] >> 6) | currenta); v12 = jb + 1; j = jb + 2; v13 = &base64[v12]; *v13 = charEncrypt(bindata[i + 2] & 0x3F); i += 3; } base64[j] = 0; return j; } |
charEncrypt函数
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 | int __cdecl base64_encode( const uint8_t *bindata, char *base64, int binlength) { int v3; // eax char *v4; // ebx int v5; // eax int v6; // ST0C_4 char *v7; // ebx int v8; // eax int v9; // eax char *v10; // ebx int v11; // eax int v12; // eax char *v13; // ebx uint8_t current; // [esp+Bh] [ebp-Dh] uint8_t currenta; // [esp+Bh] [ebp-Dh] int j; // [esp+Ch] [ebp-Ch] int ja; // [esp+Ch] [ebp-Ch] int jb; // [esp+Ch] [ebp-Ch] int i; // [esp+10h] [ebp-8h] i = 0; j = 0; while ( i < binlength ) { v3 = j; ja = j + 1; v4 = &base64[v3]; *v4 = charEncrypt((bindata[i] >> 2) & 0x3F); current = 16 * bindata[i] & 0x30; if ( i + 1 >= binlength ) { v5 = ja; v6 = ja + 1; v7 = &base64[v5]; *v7 = charEncrypt(current); base64[v6] = 61; v8 = v6 + 1; j = v6 + 2; base64[v8] = 61; break ; } v9 = ja; jb = ja + 1; v10 = &base64[v9]; *v10 = charEncrypt((bindata[i + 1] >> 4) | current); currenta = 4 * bindata[i + 1] & 0x3C; if ( i + 2 >= binlength ) { base64[jb] = charEncrypt(currenta); v11 = jb + 1; j = jb + 2; base64[v11] = '=' ; break ; } base64[jb] = charEncrypt((bindata[i + 2] >> 6) | currenta); v12 = jb + 1; j = jb + 2; v13 = &base64[v12]; *v13 = charEncrypt(bindata[i + 2] & 0x3F); i += 3; } base64[j] = 0; return j; } |
charEncrypt函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | char __cdecl charEncrypt( int data) { int dataa; // [esp+18h] [ebp+8h] dataa = aTuvwxtulmnopqr[data]; if ( dataa > '@' && dataa <= 'Z' ) return 0x9B - dataa; if ( dataa > '`' && dataa <= 'z' ) return dataa - 0x40; if ( dataa > '/' && dataa <= '9' ) return dataa + '2' ; if ( dataa == '+' ) return 'w' ; if ( dataa == '/' ) dataa = 'y' ; return dataa; } |
我们可以通过
charEncrypt函数得到真实的码表,把代码复制一份,做点小修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | char __cdecl charEncrypt( int data) { int dataa; // [esp+18h] [ebp+8h] dataa = aTuvwxtulmnopqr[data]; if ( dataa > '@' && dataa <= 'Z' ) return 0x9B - dataa; if ( dataa > '`' && dataa <= 'z' ) return dataa - 0x40; if ( dataa > '/' && dataa <= '9' ) return dataa + '2' ; if ( dataa == '+' ) return 'w' ; if ( dataa == '/' ) dataa = 'y' ; return dataa; } |
赞赏
他的文章
赞赏
雪币:
留言: