hide
這題偷雞了,不會做,說是的 upx 的殼,但似乎做了一些修改,瞎 jb 做居然做出來了。
1、運行過程中嘗試去 attach,發現已經被 trace了,那肯定是被反調試了。
2、直接運行和使用 gdb 運行結果不一致,調試情況下連輸出都沒有,直接 exit 掉了,所以肯定是被反調試了。
最開始比較害怕是多層 upx,因為調試時候看到很多次 mmap,比較害怕。反正不會做,不小心看到一個叫“在所有syscall 上下斷點”,叫 catch syscall 。
既然是加殼的,肯定會有 mmap 、 mprotect 這樣的操作,于是就”catch syscall”、”c”,這樣一直按,一直按,大概按到五六十次時候,發現了一些 ptrace,管他呢,跳過再說。之后就到了要求輸入 flag 的位置,開心,dump 一下這個內存塊,ida 打開就可以看到邏輯了!
看起來非常舒服,檢查了首尾,然后按照順序交替調用了6次加密函數。
__int64 __usercall sub_C8CC0@<rax>(unsigned int *input@<rdi>)
{
__int64 result; // rax@7
unsigned int tmp_i32; // [rsp+18h] [rbp-48h]@3
unsigned int tmp_i64[2]; // [rsp+1Ch] [rbp-44h]@3
signed int i; // [rsp+24h] [rbp-3Ch]@1
signed int j; // [rsp+28h] [rbp-38h]@3
int keyPool[4]; // [rsp+40h] [rbp-20h]@1
__int64 v7; // [rsp+58h] [rbp-8h]@1
v7 = canary;
keyPool[0] = 1883844979;
keyPool[1] = 1165112144;
keyPool[2] = 2035430262;
keyPool[3] = 861484132;
for ( i = 0; i <= 1; ++i )
{
tmp_i32 = input[2 * i];
*(_QWORD *)tmp_i64 = input[2 * i + 1];
for ( j = 0; j <= 7; ++j )
{
tmp_i32 += (keyPool[(unsigned __int64)(tmp_i64[1] & 3)] + tmp_i64[1]) ^ (((tmp_i64[0] >> 5) ^ 16 * tmp_i64[0])
+ tmp_i64[0]);
tmp_i64[1] += 1735289196;
tmp_i64[0] += (keyPool[(unsigned __int64)((tmp_i64[1] >> 11) & 3)] + tmp_i64[1]) ^ (((tmp_i32 >> 5) ^ 16 * tmp_i32)
+ tmp_i32);
}
input[2 * i] = tmp_i32;
input[2 * i + 1] = tmp_i64[0];
}
result = canary ^ v7;
if ( canary != v7 )
result = ((__int64 (*)(void))loc_C8B9A)();
return result;
}
這個很像 tea 加密,是可逆的。
char *__usercall sub_C8E50@<rax>(char *a1@<rdi>)
{
char *result; // rax@3
signed int i; // [rsp+14h] [rbp-4h]@1
for ( i = 0; i <= 15; ++i )
{
result = &a1[i];
*result ^= i;
}
return result;
}
寫個 python 反一下
keyPool = [1883844979, 1165112144, 2035430262, 861484132, ]
array_car = [1735289196, 3470578392, 910900292, 2646189488, 86511388, 1821800584, 3557089780, 997411680]
target = [0x7f13b852, 0x1bf28c35, 0xd28663f4, 0x311e4f73]
# target = [0xc234e08, 0x4ce42924, 0xd28663f4, 0x311e4f73]
# target = [0x221d5a3e, 0xd9c589da, 0x141d0409, 0x41e88c85]
def de_xor(enc):
for _i in range(4):
current = enc[_i]
a = current & 0xFF
b = (current & 0xFF00) >> 8
c = (current & 0xFF0000) >> 16
d = (current & 0xFF000000) >> 24
a ^= (_i * 4 + 0)
b ^= (_i * 4 + 1)
c ^= (_i * 4 + 2)
d ^= (_i * 4 + 3)
enc[_i] = a | (b << 8) | (c << 16) | (d << 24)
return enc
def encrypt(i32_para1, i32_para2):
foo = i32_para1
bar = i32_para2
car = 0
for _i in range(8):
tmp_a = keyPool[(car & 3)] + car
tmp_b = ((bar >> 5) ^ (bar << 4)) + bar
foo += tmp_a ^ tmp_b
foo &= 0xffffffff
car += 1735289196
car &= 0xffffffff
tmp_a = keyPool[((car >> 11) & 3)] + car
tmp_b = ((foo >> 5) ^ 16 * foo) + foo
bar += tmp_a ^ tmp_b
bar &= 0xffffffff
# print hex(foo), hex(bar), hex(car)
# array_car.append(car)
# print array_car
return foo, bar
def solver(enc_foo, enc_bar):
foo = enc_foo
bar = enc_bar
car = array_car[7]
for _i in range(8):
tmp_a = keyPool[((car >> 11) & 3)] + car
tmp_b = ((foo >> 5) ^ 16 * foo) + foo
bar -= tmp_a ^ tmp_b
bar = (bar + 0xffffffff + 1) & 0xffffffff
car -= 1735289196
car = (car + 0xffffffff + 1) & 0xffffffff
tmp_a = keyPool[(car & 3)] + car
tmp_b = ((bar >> 5) ^ (bar << 4)) + bar
foo -= tmp_a ^ tmp_b
foo = (foo + 0xffffffff + 1) & 0xffffffff
# print hex(foo), hex(bar), hex(car)
return foo, bar
target = de_xor(target)
print "====="
for t in target:
print hex(t)
for i in range(2):
target[i * 2], target[i * 2 + 1] = solver(target[i * 2], target[i * 2 + 1])
print "====="
for t in target:
print hex(t)
target = de_xor(target)
print "====="
for t in target:
print hex(t)
for i in range(2):
target[i * 2], target[i * 2 + 1] = solver(target[i * 2], target[i * 2 + 1])
print "====="
for t in target:
print hex(t)
target = de_xor(target)
print "====="
for t in target:
print hex(t)
for i in range(2):
target[i * 2], target[i * 2 + 1] = solver(target[i * 2], target[i * 2 + 1])
print "====="
for t in target:
print hex(t)
print "====="
for t in target:
print hex(t)[2:].decode('hex')[::-1]
# f1Nd_TH3HldeC0dE
2018強網杯-Writeup