发现有多种花指令,对angr不太熟,感觉通过ida_python没法直接解出,故开始了苦逼的硬逆之旅
通过在strlen下断点,可以定位到输入的位置
下硬件断点,发现是8个字节一组的分组加密,猜测是tea算法中的某一个,接下来就是验证了
接着trace与调试,看到了一些特征
还有一个 shr 11
没截下来,故猜测是xtea,接着调试可以得到是66轮
然后密钥呢
观察算法,实际上我们只要让v0,v1都等于0,让sum分别等于0,1,2,3就可以分别得到v0,v1,v2,v3
然后输入数据调试验证发现出题人没有魔改,还是很善良的ww。
接着尝试获取密文,总之还是没看到逻辑,但是看到了cmp
动调试了下发现确实是这里,故下个条件断点主动更改寄存器并将所有值打出来
然后解发现不对,试了下attach,啊发现有反调试我滴妈,一度陷入绝望
上网搜了下发现https://github.com/x64dbg/ScyllaHide/
尝试使用了下还真绕过了似乎
接着按照以上步骤再来一次 即可写出解密脚本
至于开始的单字节加密,把全部塞进去跑了下得到了个映射表,解密后映射回来即可
flag{u_ar3_re@11y_g00d_@t_011vm_de0bf_and_anti_debugger}
和学长一起做的题,熬夜脑子真是浆糊,这题把我俩套到两点多
首先是一个AES没加密,接着是一个对输入的“二进制化”,最后是一个校验,用z3解就行
这题早上起床看了一会,以前没做过游戏题,中间找到win的逻辑尝试patch赢了游戏,但是没啥发现,接着看到game.data,猜测肯定会有对data的加载过程,尝试去找,只找到了对game.record的加载过程,最终没定位到(),赛后尝试复现。
首先比赛时发现用frida调用直接寄,猜测做了反调试
不太了解windows的反调试机制,这里用插件AntiDebugSeeker
成功定位到了反调试的位置
将jnz patch 为jmp绕过
接着这里如果马后炮的话直接去康康对应的函数就行,但是今天面对这种题目确实一直找不到切入点,故考虑能否通过frida hook的方式通过对读写文件的api的监控来达到寻找切入点的目的,思考了下可能以下的步骤会有帮助:
首先查看程序加载后加载了哪些dll,查看下各个加载的dll,将其中的open,read,write等函数都hook上,最好再将exit
函数hook上,可以一定程度上防止反调试,当然如果其反调试是对逻辑的改变则一点没用。
得到以下hook脚本
可以看到,hook到了对应的ps脚本
并且可以打印出堆栈帮忙定位
这里用attch,因为spawn的话好像不太方便注入
接着dump下来ps脚本解混淆即可解
flag是73412036-7d8c-437b-9026-0c2ca1b7f79d
脚本参考DJB Team师傅发的wp
import
ida_dbg
r8d_value
=
ida_dbg.get_reg_val(
"R8D"
)
print
(f
"R8D value: 0x{r8d_value:X}"
)
ida_dbg.set_reg_val(
"EDX"
, r8d_value)
edx_value
=
ida_dbg.get_reg_val(
"EDX"
)
print
(f
"New EDX value: 0x{edx_value:X}"
)
import
ida_dbg
r8d_value
=
ida_dbg.get_reg_val(
"R8D"
)
print
(f
"R8D value: 0x{r8d_value:X}"
)
ida_dbg.set_reg_val(
"EDX"
, r8d_value)
edx_value
=
ida_dbg.get_reg_val(
"EDX"
)
print
(f
"New EDX value: 0x{edx_value:X}"
)
#include <stdio.h>
#include <stdint.h>
void
encipher(unsigned
int
num_rounds, uint32_t v[2], uint32_t
const
key[4]) {
unsigned
int
i;
uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x9E3779B9;
for
(i = 0; i < num_rounds; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
printf
(
"Round %d: v0 = %08X, v1 = %08X, sum = %08X\n"
, i + 1, v0, v1, sum);
}
v[0] = v0;
v[1] = v1;
}
void
decipher(unsigned
int
num_rounds, uint32_t v[2], uint32_t
const
key[4]) {
unsigned
int
i;
uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta * num_rounds;
for
(i = 0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0;
v[1] = v1;
}
int
main() {
uint32_t v[7][2] = {
{0x9851e3a1, 0x49765686},
{0x812b6b6f, 0x9612cecf},
{0x3c3570a2, 0xf15c6231},
{0xaa6b77fa, 0xbe056d9e},
{0xf8a424e8, 0x0b3a23db},
{0x03cc2016, 0xa92bb5ad},
{0x1d789f34, 0x9ef9b92e}
};
uint32_t v1[2] = {0x1e1e1e1e,0x1e1e1e1e};
uint32_t
const
k[4] = {0xef6fd9db, 0xd2c273d3, 0x6f97e412, 0x72bfd624};
unsigned
int
r = 0x66;
printf
(
"\n开始解密...\n"
);
for
(
int
i = 0;i<7;i++){
decipher(r, v[i], k);
printf
(
"解密后的数据:%08X %08X\n"
, v[i][0], v[i][1]);
}
return
0;
}
#include <stdio.h>
#include <stdint.h>
void
encipher(unsigned
int
num_rounds, uint32_t v[2], uint32_t
const
key[4]) {
unsigned
int
i;
uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x9E3779B9;
for
(i = 0; i < num_rounds; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
printf
(
"Round %d: v0 = %08X, v1 = %08X, sum = %08X\n"
, i + 1, v0, v1, sum);
}
v[0] = v0;
v[1] = v1;
}
void
decipher(unsigned
int
num_rounds, uint32_t v[2], uint32_t
const
key[4]) {
unsigned
int
i;
uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta * num_rounds;
for
(i = 0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0;
v[1] = v1;
}
int
main() {
uint32_t v[7][2] = {
{0x9851e3a1, 0x49765686},
{0x812b6b6f, 0x9612cecf},
{0x3c3570a2, 0xf15c6231},
{0xaa6b77fa, 0xbe056d9e},
{0xf8a424e8, 0x0b3a23db},
{0x03cc2016, 0xa92bb5ad},
{0x1d789f34, 0x9ef9b92e}
};
uint32_t v1[2] = {0x1e1e1e1e,0x1e1e1e1e};
uint32_t
const
k[4] = {0xef6fd9db, 0xd2c273d3, 0x6f97e412, 0x72bfd624};
unsigned
int
r = 0x66;
printf
(
"\n开始解密...\n"
);
for
(
int
i = 0;i<7;i++){
decipher(r, v[i], k);
printf
(
"解密后的数据:%08X %08X\n"
, v[i][0], v[i][1]);
}
return
0;
}
enc
=
[
0xD9
,
0xD3
,
0xDE
,
0xD8
,
0xC4
,
0xCA
,
0xE0
,
0xDE
,
0xCD
,
0X0C
,
0XE0
,
0Xcd
,
0Xda
,
0Xff
,
0X0e
,
0x0e
,
0xc6
,
0xe0
,
0xd8
,
0x0f
,
0x0f
,
0xdb
,
0xe0
,
0xff
,
0xcb
,
0xe0
,
0x0f
,
0x0e
,
0x0e
,
0xc9
,
0xd2
,
0xe0
,
0xdb
,
0xda
,
0x0f
,
0xdd
,
0xd9
,
0xe0
,
0xde
,
0xd1
,
0xdb
,
0xe0
,
0xde
,
0xd1
,
0xcb
,
0xd6
,
0xe0
,
0xdb
,
0xda
,
0xdd
,
0xca
,
0xd8
,
0xd8
,
0xda
,
0xcd
,
0xc2
]
print
(
len
(enc))
my_dict
=
{
0x0f
:
'0'
,
0x0e
:
'1'
,
0x0d
:
'2'
,
0x0c
:
'3'
,
0x0b
:
'4'
,
0x0a
:
'5'
,
0x09
:
'6'
,
0x08
:
'7'
,
0x07
:
'8'
,
0x06
:
'9'
,
0xde
:
'a'
,
0xdd
:
'b'
,
0xdc
:
'c'
,
0xdb
:
'd'
,
0xda
:
'e'
,
0xd9
:
'f'
,
0xd8
:
'g'
,
0xd7
:
'h'
,
0xd6
:
'i'
,
0xd5
:
'j'
,
0xd4
:
'k'
,
0xd3
:
'l'
,
0xd2
:
'm'
,
0xd1
:
'n'
,
0xd0
:
'o'
,
0xcf
:
'p'
,
0xce
:
'q'
,
0xcd
:
'r'
,
0xcc
:
's'
,
0xcb
:
't'
,
0xca
:
'u'
,
0xc9
:
'v'
,
0xc8
:
'w'
,
0xc7
:
'x'
,
0xc6
:
'y'
,
0xc5
:
'z'
,
0xfe
:
'A'
,
0xfd
:
'B'
,
0xfc
:
'C'
,
0xfb
:
'D'
,
0xfa
:
'E'
,
0xf9
:
'F'
,
0xf8
:
'G'
,
0xf7
:
'H'
,
0xf6
:
'I'
,
0xf5
:
'J'
,
0xf4
:
'K'
,
0xf3
:
'L'
,
0xf2
:
'M'
,
0xf1
:
'N'
,
0xf0
:
'O'
,
0xef
:
'P'
,
0xee
:
'Q'
,
0xed
:
'R'
,
0xec
:
'S'
,
0xeb
:
'T'
,
0x1E
:
'!'
,
0x1D
:
'"'
,
0x1C
:
'#'
,
0x1B
:
'$'
,
0x1A
:
'%'
,
0x19
:
'&'
,
0x18
: "
'", 0x17: '
(',
0x16
:
')'
,
0x15
:
'*'
,
0x14
:
'+'
,
0x13
:
','
,
0x12
:
'-'
,
0x11
:
'.'
,
0x10
:
'/'
,
0x05
:
':'
,
0x04
:
';'
,
0x03
:
'<'
,
0x02
:
'='
,
0x01
:
'>'
,
0x00
:
'?'
,
0xFF
:
'@'
,
0xE4
:
'['
,
0xE3
:
'\\'
,
0xE2
:
']'
,
0xE1
:
'^'
,
0xE0
:
'_'
,
0xDF
:
'`'
,
0xC4
:
'{'
,
0xC3
:
'|'
,
0xC2
:
'}'
,
0xC1
:
'~'
,
0xEA
:
'U'
,
0xE9
:
'V'
,
0xE8
:
'W'
,
0xE7
:
'X'
,
0xE6
:
'Y'
,
0xE5
:
'Z'
,
0xFC
:
'C'
,
0xFB
:
'D'
,
0xFA
:
'E'
,
0xF9
:
'F'
,
0xF8
:
'G'
,
0xF7
:
'H'
,
0xF6
:
'I'
,
0xF5
:
'J'
,
0xF4
:
'K'
,
0xF3
:
'L'
}
flag
=
''
for
i
in
range
(
len
(enc)):
print
(
hex
(enc[i]))
try
:
flag
+
=
my_dict[enc[i]
%
256
]
except
:
continue
print
(flag)
enc
=
[
0xD9
,
0xD3
,
0xDE
,
0xD8
,
0xC4
,
0xCA
,
0xE0
,
0xDE
,
0xCD
,
0X0C
,
0XE0
,
0Xcd
,
0Xda
,
0Xff
,
0X0e
,
0x0e
,
0xc6
,
0xe0
,
0xd8
,
0x0f
,
0x0f
,
0xdb
,
0xe0
,
0xff
,
0xcb
,
0xe0
,
0x0f
,
0x0e
,
0x0e
,
0xc9
,
0xd2
,
0xe0
,
0xdb
,
0xda
,
0x0f
,
0xdd
,
0xd9
,
0xe0
,
0xde
,
0xd1
,
0xdb
,
0xe0
,
0xde
,
0xd1
,
0xcb
,
0xd6
,
0xe0
,
0xdb
,
0xda
,
0xdd
,
0xca
,
0xd8
,
0xd8
,
0xda
,
0xcd
,
0xc2
]
print
(
len
(enc))
my_dict
=
{
0x0f
:
'0'
,
0x0e
:
'1'
,
0x0d
:
'2'
,
0x0c
:
'3'
,
0x0b
:
'4'
,
0x0a
:
'5'
,
0x09
:
'6'
,
0x08
:
'7'
,
0x07
:
'8'
,
0x06
:
'9'
,
0xde
:
'a'
,
0xdd
:
'b'
,
0xdc
:
'c'
,
0xdb
:
'd'
,
0xda
:
'e'
,
0xd9
:
'f'
,
0xd8
:
'g'
,
0xd7
:
'h'
,
0xd6
:
'i'
,
0xd5
:
'j'
,
0xd4
:
'k'
,
0xd3
:
'l'
,
0xd2
:
'm'
,
0xd1
:
'n'
,
0xd0
:
'o'
,
0xcf
:
'p'
,
0xce
:
'q'
,
0xcd
:
'r'
,
0xcc
:
's'
,
0xcb
:
't'
,
0xca
:
'u'
,
0xc9
:
'v'
,
0xc8
:
'w'
,
0xc7
:
'x'
,
0xc6
:
'y'
,
0xc5
:
'z'
,
0xfe
:
'A'
,
0xfd
:
'B'
,
0xfc
:
'C'
,
0xfb
:
'D'
,
0xfa
:
'E'
,
0xf9
:
'F'
,
0xf8
:
'G'
,
0xf7
:
'H'
,
0xf6
:
'I'
,
0xf5
:
'J'
,
0xf4
:
'K'
,
0xf3
:
'L'
,
0xf2
:
'M'
,
0xf1
:
'N'
,
0xf0
:
'O'
,
0xef
:
'P'
,
0xee
:
'Q'
,
0xed
:
'R'
,
0xec
:
'S'
,
0xeb
:
'T'
,
0x1E
:
'!'
,
0x1D
:
'"'
,
0x1C
:
'#'
,
0x1B
:
'$'
,
0x1A
:
'%'
,
0x19
:
'&'
,
0x18
: "
'", 0x17: '
(',
0x16
:
')'
,
0x15
:
'*'
,
0x14
:
'+'
,
0x13
:
','
,
0x12
:
'-'
,
0x11
:
'.'
,
0x10
:
'/'
,
0x05
:
':'
,
0x04
:
';'
,
0x03
:
'<'
,
0x02
:
'='
,
0x01
:
'>'
,
0x00
:
'?'
,
0xFF
:
'@'
,
0xE4
:
'['
,
0xE3
:
'\\'
,
0xE2
:
']'
,
0xE1
:
'^'
,
0xE0
:
'_'
,
0xDF
:
'`'
,
0xC4
:
'{'
,
0xC3
:
'|'
,
0xC2
:
'}'
,
0xC1
:
'~'
,
0xEA
:
'U'
,
0xE9
:
'V'
,
0xE8
:
'W'
,
0xE7
:
'X'
,
0xE6
:
'Y'
,
0xE5
:
'Z'
,
0xFC
:
'C'
,
0xFB
:
'D'
,
0xFA
:
'E'
,
0xF9
:
'F'
,
0xF8
:
'G'
,
0xF7
:
'H'
,
0xF6
:
'I'
,
0xF5
:
'J'
,
0xF4
:
'K'
,
0xF3
:
'L'
}
flag
=
''
for
i
in
range
(
len
(enc)):
print
(
hex
(enc[i]))
try
:
flag
+
=
my_dict[enc[i]
%
256
]
except
:
continue
最后于 13小时前
被z2zccc编辑
,原因: