没空打 就写了两题
BabySmc 先写个脚本对抗Smc
1 2 3 4 5 6 7 8 9 10 11 12 13 import idc def ror(v): v = ((v&0xf8) >> 3) | ((v&7) << 5) return v st = 0x140001085 while st <= 0x140001D00: value = idc.get_byte(st) value = ror(value) value ^= 0x5A ida_bytes.patch_byte(st, value) st += 1
去了Smc发现F5很难看,然后看汇编以及分析寄存器
可以知道是换表混淆base64
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 #include <stdio.h> unsigned char table[] ={ 0xE4 , 0xC4 , 0xE7 , 0xC7 , 0xE6 , 0xC6 , 0xE1 , 0xC1 , 0xE0 , 0xC0 , 0xE3 , 0xC3 , 0xE2 , 0xC2 , 0xED , 0xCD , 0xEC , 0xCC , 0xEF , 0xCF , 0xEE , 0xCE , 0xE9 , 0xC9 , 0xE8 , 0xC8 , 0xEB , 0xCB , 0xEA , 0xCA , 0xF5 , 0xD5 , 0xF4 , 0xD4 , 0xF7 , 0xD7 , 0xF6 , 0xD6 , 0xF1 , 0xD1 , 0xF0 , 0xD0 , 0xF3 , 0xD3 , 0xF2 , 0xD2 , 0xFD , 0xDD , 0xFC , 0xDC , 0xFF , 0xDF , 0x95 , 0x9C , 0x9D , 0x92 , 0x93 , 0x90 , 0x91 , 0x96 , 0x97 , 0x94 , 0x8A , 0x8E }; int find (int num) { for (int i = 0 ; i < 64 ; ++i) { if (num == table[i]) return i; } } int main () { char cmp[] ="H>oQn6aqLr{DH6odhdm0dMe`MBo?lRglHtGPOdobDlknejmGI|ghDb<4" ; for (int i = 0 ; cmp[i] ; i += 4 ) { char a1 = (find (cmp[i] ^ 0xA6 ) << 2 ) | (find (cmp[i+1 ] ^ 0xA3 ) >> 4 ); char a2 = (find (cmp[i+1 ] ^ 0xA3 ) << 4 ) | (find (cmp[i+2 ] ^ 0xA9 ) >> 2 ); char a3 = (find (cmp[i+2 ] ^ 0xA9 ) << 6 ) | find (cmp[i+3 ] ^ 0xAC ); printf ("%c%c%c" ,a1,a2,a3); }
SangFor{XSAYT0u5DQhaxveIR50X1U13M-pZK5A0}
safe box 第一段可以看出是输入一个int,在用这个输入去运算最后比较,
于是通过爆破解出第一段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <stdio.h> int main () { for (int i = 0 ; i < 0x7fffffff ; ++i) { int v2 = (i % 0x2540BE3FF ) & 0xff ; int v3 = ((i % 0x2540BE3FF ) >> 8 ) & 0xF ; int v4 = ((i % 0x2540BE3FF ) >> 20 ) & 0xFFF ; int v8 = v4 + ~v2; int v7 = v3 + 1 ; int v6 = ((i % 0x2540BE3FF ) >> 12 ) & 0xff ; for (int j = 0 ; j < 16 ; ++j) { v3 += v3 ^ v8; v2 += v4 | v2 & v7; v6 += v6 / v7; } if (v3 == 58722033 && v2 == 29329 && v6 == 128 ) printf ("%d\n" ,i); } }
这个程序由于是自我调试,通过管道来通信,既达到anti-debug的效果,又能够自解密
我正常输入第一段之后,程序就会进行自解密,并进入下一段
这里我选择dump出解密后的程序,再在其上分析,工具我用的是studyPE
并且将里面的CC patch以后就可以正常调试了
分析第二段可以发现,
输入的char都被放到int数组里储存,比如输入123,内存中是31000000 32000000 33000000
而后又每次取两个int作为sub_140001880的输入,经过运算后改变,再与固定数据作比较
遂又写爆破
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 void sub_7FF7547B1880 (unsigned int *input) { unsigned int a1; unsigned int v4; char v6; int v7; unsigned int v8; unsigned int v9; unsigned int v10; unsigned int v11; int v12; unsigned int v13; unsigned int v14; int v15; unsigned int v16; unsigned int v17; unsigned int v18; unsigned int v19; unsigned int a10; int a11; unsigned int a12; unsigned int a13; int a14; unsigned int a15; unsigned int a16; unsigned int a17; unsigned int a18; unsigned int a19; int v30; unsigned int v31; unsigned int v32; int v33; unsigned int v34; unsigned int v35; int v36; unsigned int v37; unsigned int v38; int v39; unsigned int v40; unsigned int v41; int v42; unsigned int v43; unsigned int v44; unsigned int v45; unsigned int v46; int v47; unsigned int v48; unsigned int v49; int v50; unsigned int v51; unsigned int v52; int v53; int GWHT[] ={0x47 ,0x57 ,0x48 ,0x54 }; a1 = input[0 ]; int a2 = input[1 ]; v4 = 0 ; v6 = 0 ; v7 = 2 ; do { v8 = v4 + GWHT[v6 & 3 ]; v9 = v4 + 0x12345678 ; v10 = (v8 ^ (a2 + ((32 * a2) ^ ((unsigned int )a2 >> 6 )))) + a1; v11 = ((v9 + GWHT[(v9 >> 11 ) & 3 ]) ^ (v10 + ((32 * v10) ^ (v10 >> 6 )))) + a2; v12 = (v9 + GWHT[v9 & 3 ]) ^ (v11 + ((32 * v11) ^ (v11 >> 6 ))); v9 += 0x12345678 ; v13 = v12 + v10; v14 = ((v9 + GWHT[(v9 >> 11 ) & 3 ]) ^ (v13 + ((32 * v13) ^ (v13 >> 6 )))) + v11; v15 = (v9 + GWHT[v9 & 3 ]) ^ (v14 + ((32 * v14) ^ (v14 >> 6 ))); v9 += 0x12345678 ; v16 = v15 + v13; v17 = ((v9 + GWHT[(v9 >> 11 ) & 3 ]) ^ (v16 + ((32 * v16) ^ (v16 >> 6 )))) + v14; v18 = v9 + GWHT[v9 & 3 ]; v9 += 0x12345678 ; v19 = (v18 ^ (v17 + ((32 * v17) ^ (v17 >> 6 )))) + v16; a10 = ((v9 + GWHT[(v9 >> 11 ) & 3 ]) ^ (v19 + ((32 * v19) ^ (v19 >> 6 )))) + v17; a11 = (v9 + GWHT[v9 & 3 ]) ^ (a10 + ((32 * a10) ^ (a10 >> 6 ))); v9 += 0x12345678 ; a12 = a11 + v19; a13 = ((v9 + GWHT[(v9 >> 11 ) & 3 ]) ^ (a12 + ((32 * a12) ^ (a12 >> 6 )))) + a10; a14 = (v9 + GWHT[v9 & 3 ]) ^ (a13 + ((32 * a13) ^ (a13 >> 6 ))); v9 += 0x12345678 ; a15 = a14 + a12; a16 = ((v9 + GWHT[(v9 >> 11 ) & 3 ]) ^ (a15 + ((32 * a15) ^ (a15 >> 6 )))) + a13; a17 = v9 + GWHT[v9 & 3 ]; v9 += 0x12345678 ; a18 = (a17 ^ (a16 + ((32 * a16) ^ (a16 >> 6 )))) + a15; a19 = ((v9 + GWHT[(v9 >> 11 ) & 3 ]) ^ (a18 + ((32 * a18) ^ (a18 >> 6 )))) + a16; v30 = (v9 + GWHT[v9 & 3 ]) ^ (a19 + ((32 * a19) ^ (a19 >> 6 ))); v9 += 0x12345678 ; v31 = v30 + a18; v32 = ((v9 + GWHT[(v9 >> 11 ) & 3 ]) ^ (v31 + ((32 * v31) ^ (v31 >> 6 )))) + a19; v33 = (v9 + GWHT[v9 & 3 ]) ^ (v32 + ((32 * v32) ^ (v32 >> 6 ))); v9 += 0x12345678 ; v34 = v33 + v31; v35 = ((v9 + GWHT[(v9 >> 11 ) & 3 ]) ^ (v34 + ((32 * v34) ^ (v34 >> 6 )))) + v32; v36 = (v9 + GWHT[v9 & 3 ]) ^ (v35 + ((32 * v35) ^ (v35 >> 6 ))); v9 += 0x12345678 ; v37 = v36 + v34; v38 = ((v9 + GWHT[(v9 >> 11 ) & 3 ]) ^ (v37 + ((32 * v37) ^ (v37 >> 6 )))) + v35; v39 = (v9 + GWHT[v9 & 3 ]) ^ (v38 + ((32 * v38) ^ (v38 >> 6 ))); v9 += 0x12345678 ; v40 = v39 + v37; v41 = ((v9 + GWHT[(v9 >> 11 ) & 3 ]) ^ (v40 + ((32 * v40) ^ (v40 >> 6 )))) + v38; v42 = (v9 + GWHT[v9 & 3 ]) ^ (v41 + ((32 * v41) ^ (v41 >> 6 ))); v9 += 0x12345678 ; v43 = v42 + v40; v44 = ((v9 + GWHT[(v9 >> 11 ) & 3 ]) ^ (v43 + ((32 * v43) ^ (v43 >> 6 )))) + v41; v45 = ((v9 + GWHT[v9 & 3 ]) ^ (v44 + ((32 * v44) ^ (v44 >> 6 )))) + v43; v9 += 0x12345678 ; v46 = ((v9 + GWHT[(v9 >> 11 ) & 3 ]) ^ (v45 + ((32 * v45) ^ (v45 >> 6 )))) + v44; v47 = (v9 + GWHT[v9 & 3 ]) ^ (v46 + ((32 * v46) ^ (v46 >> 6 ))); v9 += 0x12345678 ; v48 = v47 + v45; v49 = ((v9 + GWHT[(v9 >> 11 ) & 3 ]) ^ (v48 + ((32 * v48) ^ (v48 >> 6 )))) + v46; v50 = (v9 + GWHT[v9 & 3 ]) ^ (v49 + ((32 * v49) ^ (v49 >> 6 ))); v9 += 0x12345678 ; v51 = v50 + v48; v52 = ((v9 + GWHT[(v9 >> 11 ) & 3 ]) ^ (v51 + ((32 * v51) ^ (v51 >> 6 )))) + v49; v53 = (v9 + GWHT[v9 & 3 ]) ^ (v52 + ((32 * v52) ^ (v52 >> 6 ))); v4 = v9 + 0x12345678 ; a1 = v53 + v51; v6 = v4; a2 = ((v4 + GWHT[(v4 >> 11 ) & 3 ]) ^ (a1 + ((32 * a1) ^ (a1 >> 6 )))) + v52; --v7; } while ( v7 ); input[0 ] = a1; input[1 ] = a2; } int cmp[10 ] ={ 0x036C128C5 , 0x0C4799A63 , 0x0E8013E6C , 0x0A9F49003 , 0x0607EF54A , 0x0542C2DDF , 0x0558BD01C , 0x065512CA2 , 0x0BE1E3D05 , 0x03C467DAD , }; #include <stdio.h> int main () { for (int i = 0 ; i < 5 ; ++i) { for (int j = 0 ; j < 255 ; ++j) for (int k = 0 ; k < 255 ; ++k) { int a[2 ]= {j,k}; sub_7FF7547B1880(a); if (cmp[i * 2 ] == a[0 ] && cmp[i * 2 + 1 ] == a[1 ]) { printf ("%c%c" ,j,k); } } } }
第三段代码里面又插了个CC
分析处理debug事件的代码可以发现,改变了ecx的值
而这个ecx用作与srand()的参数
所以将代码patch成mov ecx,xxx 即可
这里也是将输入传入int数组
而在送进sub_1400025C0(v14, v13)里后v14是固定不变的
v13是输入与固定int数组经过运算得到的
而在这个函数之中,运算使用v14改变了传入的数的排列顺序,再与固定int数组比较
因为排列顺序是不变的,于是我对照传入时的v13与排列后的v13,在从cmp中一一对应
就得到了应该传入的v13
那么最后的问题就是输入与固定int数组经过了何种运算才得到了应该传入的v13了
1 2 3 4 5 6 7 8 9 movdqu xmm1, xmmword ptr [rsp+rdi+1F8h+var_1D8] movdqu xmm0, [rsp+rdi+1F8h+var_158] lea rdi, [rdi+10h] movdqa xmm2, xmm1 pand xmm2, xmm0 pxor xmm1, xmm0 pandn xmm2, xmm3 pand xmm2, xmm1 movdqu [rsp+rdi+1F8h+var_C8], xmm2
跟踪这一段,发现还是看的不是很懂
最后看了一下数据,发现有点像是异或,于是异或一下没想到出了
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 #include <stdio.h> int main () { unsigned int rands[]= { 0x4147 ,0x2F06 ,0x5017 ,0x7D6C , 0x1583 ,0x37EA ,0x6FDC ,0x0D03 , 0x3F43 ,0x4156 ,0x0ED7 ,0x1094 , 0x5C4F ,0x173F ,0x193A ,0x1357 , }; unsigned int cmp[]= { 0x4118 ,0x2F62 ,0x5027 ,0x7D33 , 0x15DA ,0x3785 ,0x6F89 ,0x0D5C , 0x3F72 ,0x413F ,0x0EBC ,0x10A7 , 0x5C10 ,0x174B ,0x190A ,0x1338 , }; for (int i = 0 ; i < 4 ; ++i) { for (int k = 0 ; k < 4 ; ++k) { printf ("%c" ,rands[i * 4 + k] ^ cmp[i * 4 + k]); } } }
所以最后的flag是
GWHT{1915969329S_s0_fuNny_d0_YoU_1ik3_t0o}