杰瑞的奶酪 无壳、32位、C++;
这里简单修改了一下变量名字;
这里很明显的加密,对输入的flag增加了当前索引值再加1;那我们只需要拿到密文减掉当前索引值再减1即可;返回拿一下密文;
这里有对密文进行了处理,因为一开始以为是个key,懒得改名字了,改了前面的截图也得换;这里的key就是密文enc;跟进看看对密文干了啥;
一个简单的异或处理,加密流程很明了了,提取密文直接解密;
其实这里不太懂,按理来说我应该是可以给动调提取key的,奈何动调发现key点不了;不管了,先赛博吧;
1 2 3 4 5 enc=[0x67 ,0x6e ,0x64 ,0x6b ,0x3f ,0x81 ,0x38 ,0x3a ,0x3c ,0x3a ,0x44 ,0x55 ,0x58 ,0x5c ,0x48 ,0x49 ,0x8e ] for i in range (len (enc)): enc[i] = enc[i] - i -1 print ('' .join(chr (c) for c in enc))
这样就可以得到flag:{12309IKN99}
杰瑞的下午茶 无壳、32位、C/C++;
看名字就觉得是个TEA,怎么说呢,做到这道题就发现这出题人喜欢给输出的字符串之类的都异或加密一下;
so?什么袅玩意,调了半天,跟TEA没有半点关系;这边还感觉有个SMC自异或的,but调了半天感觉没啥鸟用啊…;一直自异或;密文直接丢脸上么?
修完之后发现,这里最后给跳转了个地址?不懂在干啥啊…
直接对输入进行硬件断点打一下吧,看看干了啥;
直接跳转这里来了,说明这里对输入进行了操作;异或了个’3‘; 下面两个++应该就是密文和明文的比对索引了;试一试;
没招了…算法不难,调试难绷了;flag{today__is__good}
杰瑞的箱子 无壳、32位、C++;
初看甚好,再看都是vm;
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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 void __cdecl __noreturn sub_401820 (int *p_n3553585) { _DWORD *v1; _DWORD *v3; char *v4; char *v5; int v6; char n57; char *v8; char v9; char *v10; _BYTE *v11; char v12; _BYTE *v13; char n57_1; char v15; bool v16; char n57_2; char v18; _BYTE *v19; char n57_3; char v21; _BYTE *v22; _BYTE *v23; v3 = v1; LABEL_2: v3[8 ] = p_n3553585; while ( 1 ) { v4 = v3[8 ]; v5 = v4 + 1 ; v6 = *v4 - 49 ; v3[8 ] = v5; switch ( v6 ) { case 0 : sub_4011B0(v3); continue ; case 1 : n57 = *v5; v8 = v5 + 1 ; v3[8 ] = v8; if ( n57 == 57 ) { v9 = *v8; v10 = v8 + 1 ; v3[8 ] = v8 + 1 ; v11 = v8 + 2 ; v12 = *v10; v21 = v9; v3[8 ] = v11; switch ( v9 ) { case '1' : v13 = *v3; break ; case '2' : v13 = v3[1 ]; break ; case '3' : v13 = v3[2 ]; break ; case '4' : v13 = v3[3 ]; break ; case '5' : v13 = v3[4 ]; break ; case '6' : v13 = v3[5 ]; break ; case '7' : v13 = v3[6 ]; break ; case '8' : v13 = v3[7 ]; break ; case '9' : v13 = v11; break ; default : v13 = 0 ; break ; } switch ( v12 ) { case '1' : v11 = *v3; break ; case '2' : v11 = v3[1 ]; break ; case '3' : v11 = v3[2 ]; break ; case '4' : v11 = v3[3 ]; break ; case '5' : v11 = v3[4 ]; break ; case '6' : v11 = v3[5 ]; break ; case '7' : v11 = v3[6 ]; break ; case '8' : v11 = v3[7 ]; break ; case '9' : break ; default : v11 = 0 ; break ; } v23 = &v13[v11]; sub_401AC0(v21, &v23, v13); } continue ; case 2 : sub_4014B0(v3); continue ; case 3 : n57_1 = *v5; v3[8 ] = v5 + 1 ; if ( n57_1 == 57 || n57_1 == 64 ) { v15 = v5[1 ]; v16 = v3[9 ] == 1 ; v3[8 ] = v5 + 2 ; if ( !v16 ) goto LABEL_50; } continue ; case 4 : n57_2 = *v5; v3[8 ] = v5 + 1 ; if ( n57_2 == 57 ) { v18 = v5[1 ]; v19 = v5 + 2 ; v3[8 ] = v5 + 2 ; switch ( v18 ) { case '1' : v19 = *v3; break ; case '2' : v19 = v3[1 ]; break ; case '3' : v19 = v3[2 ]; break ; case '4' : v19 = v3[3 ]; break ; case '5' : v19 = v3[4 ]; break ; case '6' : v19 = v3[5 ]; break ; case '7' : v19 = v3[6 ]; break ; case '8' : v19 = v3[7 ]; break ; case '9' : break ; default : v19 = 0 ; break ; } v22 = v19 + 1 ; sub_401AC0(v18, &v22, v19); } continue ; case 5 : n57_3 = *v5; v3[8 ] = v5 + 1 ; if ( n57_3 == 57 || n57_3 == 64 ) { v15 = v5[1 ]; v16 = v3[9 ] == 1 ; v3[8 ] = v5 + 2 ; if ( v16 ) goto LABEL_50; } continue ; case 6 : v3[8 ] = v5 + 1 ; v15 = v5[1 ]; v3[8 ] = v5 + 2 ; LABEL_50: switch ( v15 ) { case 1 : p_n3553585 = v3[112 ]; goto LABEL_2; case 2 : p_n3553585 = v3[113 ]; goto LABEL_2; case 3 : p_n3553585 = v3[114 ]; goto LABEL_2; } break ; case 7 : sub_401700(v3); default : continue ; } } }
满满的VM啊,感觉像是把数组当作寄存器来操作,然后一堆操作数,其实感觉没什么实质性操作;
一个一个函数点进去,对比一下就很容易找到对比的地方其实;
这里的“=”很明显的对比,进去全给打上断点;
看左边的寄存器的比值,两个都是1;flag第一位应该就是’1‘;接着比较看看下一位;
’1‘和’9‘,那显然1是输入,9是密文了;修改一下寄存器的值,便于比较成功,继续一直动调就可以得到flag;
其实就是第二个;flag{191119118}
杰瑞的影分身 无壳、32位、C++;
找到正确的入口点;
动调一下不难发现这里有一个SMC;修一下;炸了很久…最后发现其实不用修,直接接续F7,后面会跳到一段爆红的代码;
在红色的这里按‘P’修一下
这里有个地方分析失败,直接下去nop掉;
进入伪代码发现有个异或,提取一下;
这里异或一下输入可以得到这里使用的异或流;
下面这个循环对flag没有进行处理,,但是对key进行了操作,跟进看看变化后的key;
38行显示,长度不足的用0补齐了,下面这个函数,属实是没看懂这兄弟咱传进去的参数;但是这个位置不难猜出是个加密;
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 unsigned int __cdecl Src (int a1, int a2) { _BYTE v3[80 ]; int v4; int v5; unsigned int i_1; int v7; int v8; unsigned int v9; unsigned int n15_1; unsigned int v11; int n15; unsigned int i; n15_1 = psub_4026E0(a1); i_1 = psub_4026E0(a2); psub_4026E0(byte_406274); n15 = 15 ; v11 = 15 - n15_1; if ( n15_1 != 15 ) return v11; for ( i = 0 ; i < n15_1; ++i ) { v4 = 0 ; v9 = i % 3 ; v7 = psub_401BD0(i % 3 ); v5 = (v7 + 2 ) ^ *(char *)(i + a1); v8 = *(char *)(i + a2); if ( i >= i_1 ) v8 = 0 ; v3[i] = v8 + v5; if ( (char )v3[i] != byte_406274[i] ) return i + 1 ; } return 0 ; } int __cdecl sub_401BD0 (int a1) { int v2; v2 = 0 ; switch ( a1 ) { case 0 : return 10 ; case 1 : return 9 ; case 2 : return 8 ; } return v2; }
很明了的逻辑了,就是简单的一个+2和异或key,然后再加上另一个key,然后进行密文的比较,那直接逆回去就行
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 #include <stdio.h> #include <stdint.h> int sub_401BD0 (int a1) { int v2; v2 = 0 ; switch (a1) { case 0 : return 10 ; case 1 : return 9 ; case 2 : return 8 ; } return v2; } int main () { uint8_t enc[] = {0xd3 , 0x38 , 0xD1 , 0xD3 , 0x7B , 0xAD , 0xB3 , 0x66 , 0x71 , 0x3A , 0x59 , 0x5F , 0x5F , 0x2D , 0x73 }; uint8_t key[] = {0x65 , 0x34 , 0x62 , 0x64 , 0x74 , 0x52 , 0x56 , 0x30 , 0x32 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 }; uint8_t keyy[] = {0x4 , 0x63 , 0x4 , 0x4 , 0x77 , 0x4 , 0x4 , 0x68 , 0x4 , 0x4 , 0x61 , 0x4 , 0x4 , 0x63 , 0x4 }; for (int i = 0 ; i < 15 ; i++) { enc[i] -= key[i]; enc[i] ^= (sub_401BD0(i % 3 ) + 2 ) ^ keyy[i]; printf ("%c" , enc[i]); } return 0 ; }
flag{UUU123QWE}
杰瑞的钥匙 其实这道题感觉没上一道题难受,上一道题是耗时间最长的…也有可能是因为这道题和箱子差不多的缘故;
和箱子一样,打开直接看看有哪些加密就行;
老规矩,找到判断,直接给全打断点看看,‘c’和‘=’做比较?我输入的是“a”,也就是说有其他加密,回去找一找;
给输入直接打上硬件断点跟踪看一看;一路上不知道打了多少断点;调吐了;
调得眼花,第一个加密点,+3;
第二个加密点,^7;其实调的过程中以及上面的第一个密文就可以知道其实密文就是下面这个,不说了,试试看;
flag{79453189413576}