[NPUCTF2020]BasicASM
纯考察汇编的题目,有考虑想办法改成正确的汇编形式然后编译用ida看,但感觉就失去意义了,于是硬啃汇编
00007FF7A8AC5A50 push rbp
00007FF7A8AC5A52 push rdi
00007FF7A8AC5A53 sub rsp,238h
00007FF7A8AC5A5A lea rbp,[rsp+20h]
00007FF7A8AC5A5F mov rdi,rsp
00007FF7A8AC5A62 mov ecx,8Eh
00007FF7A8AC5A67 mov eax,0CCCCCCCCh
00007FF7A8AC5A6C rep stos dword ptr [rdi]
00007FF7A8AC5A6E mov rax,qword ptr [__security_cookie (07FF7A8AD3018h)]
00007FF7A8AC5A75 xor rax,rbp
00007FF7A8AC5A78 mov qword ptr [rbp+208h],rax
00007FF7A8AC5A7F lea rcx,[__06A15900_ConsoleApplication@cpp (07FF7A8AD902Ah)]
00007FF7A8AC5A86 call __CheckForDebuggerJustMyCode (07FF7A8AC1122h)
00007FF7A8AC5A8B lea rdx,[string "flag{this_is_a_fake_flag}" (07FF7A8ACF450h)]
00007FF7A8AC5A92 lea rcx,[flag]
00007FF7A8AC5A96 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > (07FF7A8AC15E1h)
00007FF7A8AC5A9B nop
00007FF7A8AC5A9C mov dword ptr [p],0
00007FF7A8AC5AA3 mov i,0
00007FF7A8AC5AAA jmp main+64h (07FF7A8AC5AB4h)
00007FF7A8AC5AAC mov eax,i
00007FF7A8AC5AAF inc eax
00007FF7A8AC5AB1 mov i,eax
00007FF7A8AC5AB4 movsxd rax,i
00007FF7A8AC5AB8 mov qword ptr [rbp+1F8h],rax
00007FF7A8AC5ABF lea rcx,[flag]
00007FF7A8AC5AC3 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::length (07FF7A8AC122Bh)
00007FF7A8AC5AC8 mov rcx,qword ptr [rbp+1F8h]
00007FF7A8AC5ACF cmp rcx,rax
00007FF7A8AC5AD2 jae main+1B2h (07FF7A8AC5C02h) ; 无符号数比较,大于或等于时跳转
00007FF7A8AC5AD8 mov eax,i
00007FF7A8AC5ADB and eax,1 ; 取最后1位
00007FF7A8AC5ADE cmp eax,1 ; 判断奇偶
00007FF7A8AC5AE1 jne main+126h (07FF7A8AC5B76h) ; 偶数跳转(不相等跳转)
00007FF7A8AC5AE7 movsxd rax,i
00007FF7A8AC5AEB mov rdx,rax
00007FF7A8AC5AEE lea rcx,[flag]
00007FF7A8AC5AF2 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::operator[] (07FF7A8AC1442h)
00007FF7A8AC5AF7 movsx eax,byte ptr [rax] ; 取flag第i位
00007FF7A8AC5AFA xor eax,42h ; 与0x42异或
00007FF7A8AC5AFD mov dword ptr [p],eax ; 异或结果移到内存中
00007FF7A8AC5B00 mov dl,30h
00007FF7A8AC5B02 lea rcx,[rbp+144h]
00007FF7A8AC5B09 call std::setfill<char> (07FF7A8AC1046h) ; 用字符'0'进行填充
00007FF7A8AC5B0E mov qword ptr [rbp+1F8h],rax
00007FF7A8AC5B15 mov edx,2
00007FF7A8AC5B1A lea rcx,[rbp+168h]
00007FF7A8AC5B21 call std::setw (07FF7A8AC10D2h) ; 填充至2位
00007FF7A8AC5B26 mov qword ptr [rbp+200h],rax
00007FF7A8AC5B2D lea rdx,[std::hex (07FF7A8AC1488h)] ; 以十六进制形式输出
00007FF7A8AC5B34 mov rcx,qword ptr [__imp_std::cout (07FF7A8AD71C0h)]
00007FF7A8AC5B3B call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF7A8AD7160h)]
00007FF7A8AC5B41 mov rcx,qword ptr [rbp+200h]
00007FF7A8AC5B48 mov rdx,rcx
00007FF7A8AC5B4B mov rcx,rax
00007FF7A8AC5B4E call std::operator<<<char,std::char_traits<char>,__int64> (07FF7A8AC12F8h)
00007FF7A8AC5B53 mov rcx,qword ptr [rbp+1F8h]
00007FF7A8AC5B5A mov rdx,rcx
00007FF7A8AC5B5D mov rcx,rax
00007FF7A8AC5B60 call std::operator<<<char,std::char_traits<char>,char> (07FF7A8AC11A4h)
00007FF7A8AC5B65 mov edx,dword ptr [p]
00007FF7A8AC5B68 mov rcx,rax
00007FF7A8AC5B6B call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF7A8AD7158h)]
00007FF7A8AC5B71 jmp main+1ADh (07FF7A8AC5BFDh)
00007FF7A8AC5B76 movsxd rax,i ; 偶数时跳转到这里,与奇数唯一的区别为没有异或运算
00007FF7A8AC5B7A mov rdx,rax
00007FF7A8AC5B7D lea rcx,[flag]
00007FF7A8AC5B81 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::operator[] (07FF7A8AC1442h)
00007FF7A8AC5B86 movsx eax,byte ptr [rax]
00007FF7A8AC5B89 mov dword ptr [p],eax
00007FF7A8AC5B8C mov dl,30h
00007FF7A8AC5B8E lea rcx,[rbp+194h]
00007FF7A8AC5B95 call std::setfill<char> (07FF7A8AC1046h)
00007FF7A8AC5B9A mov qword ptr [rbp+1F8h],rax
00007FF7A8AC5BA1 mov edx,2
00007FF7A8AC5BA6 lea rcx,[rbp+1B8h]
00007FF7A8AC5BAD call std::setw (07FF7A8AC10D2h)
00007FF7A8AC5BB2 mov qword ptr [rbp+200h],rax
00007FF7A8AC5BB9 lea rdx,[std::hex (07FF7A8AC1488h)]
00007FF7A8AC5BC0 mov rcx,qword ptr [__imp_std::cout (07FF7A8AD71C0h)]
00007FF7A8AC5BC7 call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF7A8AD7160h)]
00007FF7A8AC5BCD mov rcx,qword ptr [rbp+200h]
00007FF7A8AC5BD4 mov rdx,rcx
00007FF7A8AC5BD7 mov rcx,rax
00007FF7A8AC5BDA call std::operator<<<char,std::char_traits<char>,__int64> (07FF7A8AC12F8h)
00007FF7A8AC5BDF mov rcx,qword ptr [rbp+1F8h]
00007FF7A8AC5BE6 mov rdx,rcx
00007FF7A8AC5BE9 mov rcx,rax
00007FF7A8AC5BEC call std::operator<<<char,std::char_traits<char>,char> (07FF7A8AC11A4h)
00007FF7A8AC5BF1 mov edx,dword ptr [p]
00007FF7A8AC5BF4 mov rcx,rax
00007FF7A8AC5BF7 call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF7A8AD7158h)]
00007FF7A8AC5BFD jmp main+5Ch (07FF7A8AC5AACh)
00007FF7A8AC5C02 mov dword ptr [rbp+1E4h],0
00007FF7A8AC5C0C lea rcx,[flag]
00007FF7A8AC5C10 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> > (07FF7A8AC1302h)
00007FF7A8AC5C15 mov eax,dword ptr [rbp+1E4h]
00007FF7A8AC5C1B mov edi,eax
00007FF7A8AC5C1D lea rcx,[rbp-20h]
00007FF7A8AC5C21 lea rdx,[__xt_z+540h (07FF7A8ACEFE0h)]
00007FF7A8AC5C28 call _RTC_CheckStackVars (07FF7A8AC1596h)
00007FF7A8AC5C2D mov eax,edi
00007FF7A8AC5C2F mov rcx,qword ptr [rbp+208h]
00007FF7A8AC5C36 xor rcx,rbp
00007FF7A8AC5C39 call __security_check_cookie (07FF7A8AC1190h)
00007FF7A8AC5C3E lea rsp,[rbp+218h]
00007FF7A8AC5C45 pop rdi
00007FF7A8AC5C46 pop rbp
00007FF7A8AC5C47 ret
简单的说,过程就是一个循环,根据 i
的奇偶进行判断,是否与 0x42
进行异或,然后将结果以 2 位十六进制输出,所以只需要进行反向求解即可
from libnum import n2s
cipher = n2s(0x662e61257b26301d7972751d6b2c6f355f3a38742d74341d61776d7d7d)
for i in range(len(cipher)):
if i & 1 == 1:
print (chr(cipher[i] ^ 0x42), end = '')
else:
print (chr(cipher[i]), end = '')
# flag{d0_y0u_know_x86-64_a5m?}
[watevrCTF 2019]Repyc
010看一眼,发现文件头好像没什么问题,直接用 uncompyle6
转成python文件
和VN的题一样,变量都成了乱码,阅读一下然后改一改
zero = 0
one = 1
two = 2
def function(op):
i = zero
list_a = [zero] * two ** (two * two) # [0] * 16
list_b = [zero] * 100
list_c = []
while op[i][zero] != 'nop':
print (i, op[i])
cur = op[i][zero].lower()
args = op[i][one:]
if cur == 'add':
list_a[args[zero]] = list_a[args[one]] + list_a[args[two]]
elif cur == 'xor':
list_a[args[zero]] = list_a[args[one]] ^ list_a[args[two]]
elif cur == 'sub':
list_a[args[zero]] = list_a[args[one]] - list_a[args[two]]
elif cur == 'mul':
list_a[args[zero]] = list_a[args[one]] * list_a[args[two]]
elif cur == 'div':
list_a[args[zero]] = list_a[args[one]] / list_a[args[two]]
elif cur == 'and':
list_a[args[zero]] = list_a[args[one]] & list_a[args[two]]
elif cur == 'or':
list_a[args[zero]] = list_a[args[one]] | list_a[args[two]]
elif cur == 'nothing':
list_a[args[zero]] = list_a[args[zero]]
elif cur == 'mov':
list_a[args[zero]] = args[one]
elif cur == 'set_a':
list_a[args[zero]] = list_b[args[one]]
elif cur == 'clear':
list_a[args[zero]] = zero
elif cur == 'input_b':
list_b[args[zero]] = input(list_a[args[one]])
elif cur == 'print_a':
print(list_a[args[zero]])
elif cur == 'c_pop':
i = list_c.pop()
elif cur == 'append_c':
list_a[7] = zero
for j in range(len(list_a[args[zero]])):
if list_a[args[zero]] != list_a[args[one]]:
list_a[7] = one
i = list_a[args[two]]
list_c.append(i)
elif cur == 'xor_a':
str_next = ''
for j in range(len(list_a[args[zero]])):
str_next += chr(ord(list_a[args[zero]][j]) ^ list_a[args[one]])
list_a[args[zero]] = str_next
elif cur == 'sub_a':
str_next = ''
for j in range(len(list_a[args[zero]])):
str_next += chr(ord(list_a[args[zero]][j]) - list_a[args[one]])
list_a[args[zero]] = str_next
print (list_a)
print (list_b)
print (list_c)
print ()
i += one
function(
[
[ 'mov', zero, 'Authentication token: '],
# 将这个字符串放到list a的0号位置
[ 'input_b', zero, zero],
# 将输入放到list b的0号位置
[ 'mov', 6, 'á×äÓâæíäàßåÉÛãåäÉÖÓÉäàÓÉÖÓåäÉÓÚÕæïèäßÙÚÉÛÓäàÙÔÉÓâæÉàÓÚÕÓÒÙæäàÉäàßåÉßåÉäàÓÉÚÓáÉ·Ôâ×ÚÕÓÔɳÚÕæïèäßÙÚÉÅä×ÚÔ×æÔÉ×Úïá×ïåÉßÉÔÙÚäÉæÓ×ÜÜïÉà×âÓÉ×ÉÑÙÙÔÉâßÔÉÖãäÉßÉæÓ×ÜÜïÉÓÚÞÙïÉäàßåÉåÙÚÑÉßÉàÙèÓÉïÙãÉáßÜÜÉÓÚÞÙïÉßäÉ×åáÓÜÜ\x97ÉïÙãäãÖÓ\x9aÕÙÛ\x99á×äÕà©â«³£ï²ÕÔÈ·±â¨ë'],
# 将这个字符串放到list a的6号位置
[ 'mov', two, two ** (3 * two + one) - two ** (two + one)],
# 将120放到list a的2号位置
[ 'mov', 4, 15],
# 将15放到list a的4号位置
[ 'mov', 3, one],
# 将1放到list a的3号位置
[ 'mul', two, two, 3],
# list a的2号位置等于2号位置*3号位置,即不变
[ 'add', two, two, 4],
# list a的2号位置等于2号位置+4号位置,即120变为135
[ 'nothing', zero, two],
[ 'clear', 3],
# list a的3号位置清零
[ 'xor_a', 6, 3],
# 6号位置中每一个字符与3异或
[ 'mov', zero, 'Thanks.'],
[ 'mov', one, 'Authorizing access...'],
[ 'print_a', zero],
[ 'set_a', zero, zero],
[ 'xor_a', zero, two], # 输入异或135
[ 'sub_a', zero, 4], # 输入减15
[ 'mov', 5, 19],
[ 'append_c', zero, 6, 5],
[ 'print_a', one],
[ 'nop'],
[ 'mov', one, 'Access denied!'],
[ 'print_a', one],
[ 'nop']
]
)
将过程变量输出当作动调,就比较容易看懂每条指令在干什么了
最后发现有用的就是异或135和减15,猜flag头是 watevr
,果然和密文前6个字符对上了
所以直接一个解密就行
cipher = 'á×äÓâæíäàßåÉÛãåäÉÖÓÉäàÓÉÖÓåäÉÓÚÕæïèäßÙÚÉÛÓäàÙÔÉÓâæÉàÓÚÕÓÒÙæäàÉäàßåÉßåÉäàÓÉÚÓáÉ·Ôâ×ÚÕÓÔɳÚÕæïèäßÙÚÉÅä×ÚÔ×æÔÉ×Úïá×ïåÉßÉÔÙÚäÉæÓ×ÜÜïÉà×âÓÉ×ÉÑÙÙÔÉâßÔÉÖãäÉßÉæÓ×ÜÜïÉÓÚÞÙïÉäàßåÉåÙÚÑÉßÉàÙèÓÉïÙãÉáßÜÜÉÓÚÞÙïÉßäÉ×åáÓÜÜ\x97ÉïÙãäãÖÓ\x9aÕÙÛ\x99á×äÕà©â«³£ï²ÕÔÈ·±â¨ë'
for c in cipher:
print (chr((ord(c) + 15) ^ 135), end = '')
# watevr{this_must_be_the_best_encryption_method_evr_henceforth_this_is_the_new_Advanced_Encryption_Standard_anyways_i_dont_really_have_a_good_vid_but_i_really_enjoy_this_song_i_hope_you_will_enjoy_it_aswell!_youtube.com/watch?v=E5yFcdPAGv0}
[watevrCTF 2019]esreveR
用ida打开后,发现大量与输入无关的计算,于是决定先静态跟踪一下输入,然后再动调看过程数据
和输入有关的大概是这些(动调后写的wp,所以基地址改变了)
fgets(s, n[0], stdin);
v8 = sub_5578E4A20943(n[0]);
*(_QWORD *)n = sub_5578E4A20996(v14);
if ( *(_QWORD *)n != v8 )
{
v11 = sub_5578E4A209E9(4521);
if ( s != (char *)v11 )
{
v4 = sub_5578E4A212D8((__int64)s, v15, v10, v9, v11, v13);
if ( v4 != v15 * ((v12 ^ v13) - *(_QWORD *)n) )
puts("Congratulations! You reversed the reversed reverse!");
}
}
发现输入只要输入的地址不等于一个数,然后通过某个判断就行,于是再进到判断前的函数
会看到一个输入参数很多的函数,进去看一下
v58 = a1 == *a57;
if ( a2 != a57[1] )
v58 = 0;
if ( a3 != a57[2] )
v58 = 0;
if ( a4 != a57[3] )
v58 = 0;
if ( a5 != a57[4] )
v58 = 0;
// 以下省略
输入了57个参数,而且就是判断是否相同的,相同就返回1,否则返回0
于是猜测这里就是最终的验证函数
中间经过了一系列动调,确定其它的过程没什么影响,于是在进入函数前下个断点,然后直接去rsp的地址里找比较的数据
最后的内存数据
[stack]:00007FFF9B4402F0 dq '{', 'e', 's', 'r', 'e', 'v', 'e', 'r', '_', 'r', 'e', 'v', 'e', 'r', 's', 'e'
[stack]:00007FFF9B4402F0 dq 'd', '_', 'y', 'o', 'u', 't', 'u', 'b', 'e', '.', 'c', 'o', 'm', '/', 'w', 'a'
[stack]:00007FFF9B4402F0 dq 't', 'c', 'h', '?', 'v', '=', 'I', '8', 'i', 'j', 'b', '4', 'Z', 'e', 'e', '5'
[stack]:00007FFF9B4402F0 dq 'E', '}'
连接起来就是flag了
{esrever_reversed_youtube.com/watch?v=I8ijb4Zee5E}
firmware
一道水题,主要学习一下工控逆向
不难看出,给的附件是squashfs文件,直接进行binwalk
在安装sasquatch时遇到了一些坑,好像必须clone到~/Downloads等文件夹内才行
binwalk之后逛一下目录,能够找到一个叫做 backdoor
的二进制文件
目标是找到连接的ip和端口,进去找一找就能看到
[MR2020]Shit
这题最后的解法很屑(
首先是去花,但花指令和CISCN2021-N的RE2一样,就不细说了
一直尝试反调试,但一直没成功,就用爆破来解了…
char __cdecl sub_DA12F0(const char *a1)
{
int v2; // [esp+14h] [ebp-14h]
int i; // [esp+1Ch] [ebp-Ch]
int v4; // [esp+20h] [ebp-8h]
int v5; // [esp+20h] [ebp-8h]
v2 = 0;
for ( i = 0; i < strlen(a1); i += 4 )
{
v4 = __ROR4__(a1[i + 3] | (a1[i + 2] << 8) | (a1[i + 1] << 16) | (a1[i] << 24), dword_DA5034[i / 4]);
v5 = ((v4 << 16) | (unsigned __int16)~HIWORD(v4)) ^ (1 << dword_DA5034[i / 4]);
if ( i > 0 )
v5 ^= v2;
v2 = v5;
if ( v5 != dword_DA5018[i / 4] )
return 0;
}
return 1;
}
既然每四位进行一系列位运算,且密钥只有六位,那就爆破吧
from libnum import *
a = [0x8C2C133A, 0x0F74CB3F6, 0x0FEDFA6F2, 0x0AB293E3B, 0x26CF8A2A, 0x88A1F279]
for t in range(len(a)):
for i in range(32):
tmp = a[t]
if t != 0:
tmp = tmp ^ a[t - 1]
tmp = tmp ^ (1 << i)
tmp = ((~tmp & 0xffff) << 16) | (tmp >> 16)
res = n2s(((tmp >> (0x20 - i)) | (tmp << i)) & 0xffffffff)
if res[0] > 0x20 and res[0] < 0x7f:
if res[1] > 0x20 and res[1] < 0x7f:
if res[2] > 0x20 and res[2] < 0x7f:
if res[3] > 0x20 and res[3] < 0x7f:
print (res)
print ()
最后甚至直接上四个 if
了…
爆破结果
b'flag' # 必选
b',ag&'
b"a'f,"
b'gf,!'
b'_2{`'
b'3{`^'
b'{a_3' # 必选
b'`_3z'
b'[a2}'
b'a2y_' # 剩下三个有大括号,排除
b'6}_a'
b'}_e2'
b're_f'
b'e_gs'
b'^fse'
b'fsd_'
b'_4o2'
b'or_t'
b'2_t/'
b'=%st'
b'est}' # 必选
b's4=e'
b't=e3'
中间根据前后单词拼接一下就行了
- Shit这道题还是要看一下别人的WP,学习一下正确的思路
[SUCTF2018]HelloPython
uncompyle6
(lambda __target: [ (lambda __target: [ [ __this() for __g['n'] in [__operator.isub(__g['n'], 1)] ][0] for __target.value in [__operator.iadd(__target.value, (y.value << 4) + k[2] ^ y.value + x.value ^ (y.value >> 5) + k[3])] ][0])(z) for __target.value in [__operator.iadd(__target.value, (z.value << 4) + k[0] ^ z.value + x.value ^ (z.value >> 5) + k[1])] ][0])(y)
很明显是tea
void encrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i < 32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
} /* end cycle */
v[0]=v0; v[1]=v1;
}
对比一下,z是v[1],x是sum,y是v[0],或者看下面这段
for __g['x'] in [c_uint32(0)] ][0] for __g['z'] in [c_uint32(v[1])] ][0] for __g['y'] in [c_uint32(v[0])]
delta常数
for __g['u'] in [2654435769]
密钥常数
for __g['k'] in [[3735928559, 590558003, 19088743, 4275878552]]
到题目描述里找到密文 f1f5d29b6e4414ec
(这还得自己去github找,离谱)
解密
#include <stdio.h>
#include <stdint.h>
//加密函数
void encrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i < 32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
} /* end cycle */
v[0]=v0; v[1]=v1;
}
//解密函数
void decrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i<32; i++) { /* basic cycle start */
v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
sum -= delta;
} /* end cycle */
v[0]=v0; v[1]=v1;
}
int main()
{
uint32_t v[2]={0xf1f5d29b, 0x6e4414ec},k[4]={3735928559, 590558003, 19088743, 4275878552};
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
// printf("加密前原始数据:%u %u\n",v[0],v[1]);
// encrypt(v, k);
// printf("加密后的数据:%u %u\n",v[0],v[1]);
decrypt(v, k);
printf("解密后的数据:%x %x\n",v[0],v[1]);
return 0;
}
[FBCTF]go_get_the_flag
没想到能在第五页见到memequal的题,真正的baby
[Zer0pts2020]QR Puzzle
QR文件是25*25的字符串,每一位都是字符0或1
key文件每一行格式为 a#(b,c)
,最后存储到链表中,末尾在前,具体结构为 int b, int c, int a, 0, *next
从加密函数来看,应该是一个vm
简单整理一下
void __fastcall sub_400BD0(__int64 a1, int *a2)
{
int v2; // er8
int v3; // edx
_QWORD *v4; // r9
_QWORD *v5; // rcx
int v6; // er9
__int64 v7; // rax
__int64 v8; // rcx
while ( a2 ) {
x = a2[2];
y = a2[0];
z = a2[1];
if ( x == 1 ) {
v2 = z;
v3 = y + 1;
goto LABEL_4;
}
if ( x == 0 ) {
v2 = z;
v3 = y - 1;
goto LABEL_4;
}
if ( x == 3 ) {
v2 = z + 1;
v3 = y;
goto LABEL_4;
}
if ( x == 2 ) {
v2 = z - 1;
v3 = y;
}
LABEL_4:
v4 = &a1[z];
v5 = &a1[v2];
*(_BYTE *)(v7 + *v4) += *(_BYTE *)(*v5 + v3);
*(_BYTE *)(v3 + *v5) = *(_BYTE *)(*v4 + v7) - *(_BYTE *)(v3 + *v5);
*(_BYTE *)(*v4 + v7) -= *(_BYTE *)(*v5 + v3); // 经典swap
a2 = (int *)*((_QWORD *)a2 + 2); // a2 = a2->next
}
}
显然加密就是和周围某个位置交换一下
解密和加密是对称的,直接把key文件反转过来,就是解密了
接下来需要把01串变成图片
from PIL import Image
def black_block(image, x, y):
for i in range(5):
for j in range(5):
image.putpixel((x + i, y + j), (0, 0, 0))
im = Image.new('RGB', (125, 125), "#FFFFFF")
flag = [
'1111111001000101001111111',
'1000001011001001001000001',
'1011101001110011101011101',
'1011101001100010101011101',
'1011101011000111001011101',
'1000001001110111101000001',
'1111111010101010101111111',
'0000000000101101100000000',
'1010101000001110000010010',
'0011100010000110101001001',
'1001001100011110111010011',
'1110110110001111000101000',
'0101001011011100011101011',
'0101100101111010101001011',
'1001011011011000000100111',
'0101010010001110011110011',
'1001101001110010111111000',
'0000000011110000100011001',
'1111111001100101101010111',
'1000001001010001100010000',
'1011101011101000111111011',
'1011101000111101000010000',
'1011101010111011010110101',
'1000001001001111111010010',
'1111111011110011100011011'
]
for i in range(len(flag)):
for j in range(len(flag[0])):
if flag[i][j] == '1':
black_block(im, i * 5, j * 5)
im.show()
扫描二维码拿flag
[XMAN2018排位赛]easyvm
vm题,上来先把字节翻译成汇编格式
vm_code = [
0x05, 0x01, 0x0B, 0x13, 0x03, 0x03, 0x13, 0x00, 0x00, 0x13,
0x04, 0x04, 0x28, 0x0C, 0x00, 0x33, 0x14, 0x00, 0x20, 0x05,
0x09, 0x01, 0x11, 0x09, 0x00, 0x0B, 0x0A, 0x09, 0x01, 0x04,
0x0A, 0x1B, 0x05, 0x04, 0x0C, 0x03, 0x01, 0x24, 0x03, 0x20,
0x28, 0x13, 0x00, 0x00, 0x07, 0x08, 0x05, 0x0E, 0x08, 0xE0,
0x07, 0x02, 0x08, 0x09, 0x0A, 0x02, 0x01, 0x00, 0x0A, 0x18,
0x00, 0xE0, 0x1E, 0x00, 0x05, 0x01, 0x04, 0x00, 0x13, 0x03,
0x03, 0x28, 0x09, 0x0A, 0x02, 0x01, 0x00, 0x0A, 0x18, 0x00,
0x1F, 0x20, 0x00, 0x03, 0x1B, 0x05, 0x00, 0x07, 0x08, 0x05,
0x0E, 0x08, 0xE0, 0x07, 0x02, 0x08, 0x09, 0x0A, 0x02, 0x01,
0x00, 0x0A, 0x18, 0x00, 0xE0, 0x1E, 0x00, 0x05, 0x1D, 0x05,
0x0A, 0x0D, 0x0A, 0x00, 0x1B, 0x05, 0x0A, 0x0C, 0x03, 0x01,
0x24, 0x03, 0x1F, 0x28, 0x09, 0x0A, 0x02, 0x01, 0x00, 0x0A,
0x18, 0x00, 0x1F, 0x20, 0x00, 0x03, 0x0D, 0x00, 0x04, 0x1B,
0x05, 0x00, 0x13, 0x03, 0x03, 0x03, 0x04, 0x0D, 0x28, 0x07,
0x08, 0x05, 0x0E, 0x08, 0xE0, 0x07, 0x02, 0x08, 0x09, 0x0A,
0x02, 0x01, 0x00, 0x0A, 0x1B, 0x05, 0x00, 0x01, 0x00, 0x04,
0x0D, 0x00, 0x03, 0x1D, 0x05, 0x0A, 0x13, 0x0A, 0x00, 0x1B,
0x05, 0x0A, 0x22, 0x04, 0x08, 0x0C, 0x03, 0x01, 0x24, 0x03,
0x20, 0x28, 0x13, 0x03, 0x03, 0x13, 0x04, 0x04, 0x05, 0x01,
0x0C, 0x28, 0x05, 0x09, 0x01, 0x11, 0x09, 0x03, 0x0B, 0x0A,
0x09, 0x01, 0x00, 0x0A, 0x1B, 0x05, 0x00, 0x07, 0x08, 0x05,
0x0E, 0x08, 0xDF, 0x09, 0x0A, 0x08, 0x1D, 0x05, 0x00, 0x1B,
0x05, 0x00, 0x27, 0x00, 0x0A, 0x17, 0x04, 0x07, 0x0C, 0x03,
0x01, 0x24, 0x03, 0x20, 0x28, 0x2A, 0x00, 0x00
]
index = 0
length = len(vm_code)
inloop = 0
while index < length:
v22 = vm_code[index]
v6 = vm_code[index + 1]
v5 = vm_code[index + 2]
v21 = vm_code[index] & 0xFE
v20 = vm_code[index] & 1
if v21 == 0:
if v20 == 1:
print (f'_{index}: mov v23[{v6}], v23[{v5}]')
if v20 == 0:
print (f'_{index}: mov v23[{v6}], {v5}')
index += 2
elif v21 == 2:
if v20 == 1:
print (f'_{index}: mov32 v23[{v6}], v23[{v5}]')
if v20 == 0:
print (f'_{index}: mov32 v23[{v6}], {v5}')
index += 2
elif v21 == 4:
if v20 == 1:
print (f'_{index}: lea_ch v23[{v6}], v23[{v5}]')
index += 2
elif v21 == 6:
if v20 == 1:
print (f'_{index}: lea_int v23[{v6}], v23[{v5}]')
index += 2
elif v21 == 8:
if v20 == 1:
print (f'_{index}: ldr_int v23[{v6}], v23[{v5}]')
index += 2
elif v21 == 0xA:
if v20 == 1:
print (f'_{index}: ldr_ch v23[{v6}], v23[{v5}]')
index += 2
elif v21 == 0xC:
if v20 == 1:
print (f'_{index}: add v23[{v6}], v23[{v5}]')
if v20 == 0:
print (f'_{index}: add v23[{v6}], {v5}')
index += 2
elif v21 == 0xE:
if v20 == 1:
print (f'_{index}: add_pint v23[{v6}], v23[{v5}]')
if v20 == 0:
print (f'_{index}: add_pint v23[{v6}], {v5}')
index += 2
elif v21 == 0x10:
if v20 == 1:
print (f'_{index}: add_pch v23[{v6}], v23[{v5}]')
if v20 == 0:
print (f'_{index}: add_pch v23[{v6}], {v5}')
index += 2
elif v21 == 0x12:
if v20 == 1:
print (f'_{index}: my_xor v23[{v6}], v23[{v5}]')
if v20 == 0:
print (f'_{index}: my_xor v23[{v6}], {v5}')
index += 2
elif v21 == 0x14:
if v20 == 0:
print (f'_{index}: mod v23[{v6}], {v5}')
index += 2
elif v21 == 0x16:
if v20 == 1:
print (f'_{index}: my_or v23[{v6}], v23[{v5}]')
if v20 == 0:
print (f'_{index}: my_or v23[{v6}], {v5}')
index += 2
elif v21 == 0x18:
if v20 == 1:
print (f'_{index}: my_and v23[{v6}], v23[{v5}]')
if v20 == 0:
print (f'_{index}: my_and v23[{v6}], {v5}')
index += 2
elif v21 == 0x1A:
if v20 == 1:
print (f'_{index}: push v23[{v6}], v23[{v5}]')
if v20 == 0:
print (f'_{index}: push v23[{v6}], {v5}')
index += 2
elif v21 == 0x1C:
if v20 == 1:
print (f'_{index}: pop v23[{v6}], v23[{v5}]')
index += 2
elif v21 == 0x1E:
if v20 == 1:
print (f'_{index}: shr v23[{v6}], v23[{v5}]')
if v20 == 0:
print (f'_{index}: shr v23[{v6}], {v5}')
index += 2
elif v21 == 0x20:
if v20 == 1:
print (f'_{index}: shl v23[{v6}], v23[{v5}]')
if v20 == 0:
print (f'_{index}: shl v23[{v6}], {v5}')
index += 2
elif v21 == 0x22:
if v20 == 1:
print (f'_{index}: ror v23[{v6}], v23[{v5}]')
if v20 == 0:
print (f'_{index}: ror v23[{v6}], {v5}')
index += 2
elif v21 == 0x24:
if v20 == 1:
print (f'_{index}: cmpl v23[{v6}], v23[{v5}]')
if v20 == 0:
print (f'_{index}: cmpl v23[{v6}], {v5}')
index += 2
elif v21 == 0x26:
if v20 == 1:
print (f'_{index}: cmpeq v23[{v6}], v23[{v5}]')
if v20 == 0:
print (f'_{index}: cmpeq v23[{v6}], {v5}')
index += 2
elif v21 == 0x28:
if inloop == 0:
print (f'\n_{index}: start_loop')
inloop = 1
elif inloop == 1:
print (f'_{index}: end_loop\n')
inloop = 0
elif v21 == 0x2A:
print (f'_{index}: judge')
break
index += 1
转换结果
_0: lea_ch v23[1], v23[11]
_3: my_xor v23[3], v23[3]
_6: my_xor v23[0], v23[0]
_9: my_xor v23[4], v23[4]
_12: start_loop
_13: add v23[0], 51
_16: mod v23[0], 32
_19: lea_ch v23[9], v23[1]
_22: add_pch v23[9], v23[0]
_25: ldr_ch v23[10], v23[9]
_28: mov v23[4], v23[10]
_31: push v23[5], v23[4]
_34: add v23[3], 1
_37: cmpl v23[3], 32
_40: end_loop
_41: my_xor v23[0], v23[0]
_44: lea_int v23[8], v23[5]
_47: add_pint v23[8], 224
_50: lea_int v23[2], v23[8]
_53: ldr_int v23[10], v23[2]
_56: mov v23[0], v23[10]
_59: my_and v23[0], 224
_62: shr v23[0], 5
_65: mov v23[4], v23[0]
_68: my_xor v23[3], v23[3]
_71: start_loop
_72: ldr_int v23[10], v23[2]
_75: mov v23[0], v23[10]
_78: my_and v23[0], 31
_81: shl v23[0], 3
_84: push v23[5], v23[0]
_87: lea_int v23[8], v23[5]
_90: add_pint v23[8], 224
_93: lea_int v23[2], v23[8]
_96: ldr_int v23[10], v23[2]
_99: mov v23[0], v23[10]
_102: my_and v23[0], 224
_105: shr v23[0], 5
_108: pop v23[5], v23[10]
_111: add v23[10], v23[0]
_114: push v23[5], v23[10]
_117: add v23[3], 1
_120: cmpl v23[3], 31
_123: end_loop
_124: ldr_int v23[10], v23[2]
_127: mov v23[0], v23[10]
_130: my_and v23[0], 31
_133: shl v23[0], 3
_136: add v23[0], v23[4]
_139: push v23[5], v23[0]
_142: my_xor v23[3], v23[3]
_145: mov32 v23[4], v23[13]
_148: start_loop
_149: lea_int v23[8], v23[5]
_152: add_pint v23[8], 224
_155: lea_int v23[2], v23[8]
_158: ldr_int v23[10], v23[2]
_161: mov v23[0], v23[10]
_164: push v23[5], v23[0]
_167: mov v23[0], v23[4]
_170: add v23[0], v23[3]
_173: pop v23[5], v23[10]
_176: my_xor v23[10], v23[0]
_179: push v23[5], v23[10]
_182: ror v23[4], 8
_185: add v23[3], 1
_188: cmpl v23[3], 32
_191: end_loop
_192: my_xor v23[3], v23[3]
_195: my_xor v23[4], v23[4]
_198: lea_ch v23[1], v23[12]
_201: start_loop
_202: lea_ch v23[9], v23[1]
_205: add_pch v23[9], v23[3]
_208: ldr_ch v23[10], v23[9]
_211: mov v23[0], v23[10]
_214: push v23[5], v23[0]
_217: lea_int v23[8], v23[5]
_220: add_pint v23[8], 223
_223: ldr_int v23[10], v23[8]
_226: pop v23[5], v23[0]
_229: push v23[5], v23[0]
_232: cmpeq v23[0], v23[10]
_235: my_or v23[4], v23[7]
_238: add v23[3], 1
_241: cmpl v23[3], 32
_244: end_loop
_245: judge
因为是Mach-O文件,不会动调,只能看静态了(成功被指针恶心到了,算法全靠猜)
第一个循环就是进行了一个顺序上的转换(类似栅栏吧)
第二个循环看到有先右移5bit,再左移3bit,一开始猜测可能是字节内部转换,后来发现在循环的前也有个右移,循环后也有个左移,代码几乎都一样,猜测是所有字节一起进行位移
第三个循环注意到有个 ror
的循环右移,然后还有异或,就是每次异或一个字节
最后写一个解密,从文件里dump出密文和key
cipher = [
0x75, 0x85, 0xD1, 0x39, 0x0B, 0x29, 0xCD, 0x77, 0x6D, 0x9F,
0x73, 0x23, 0x61, 0x8B, 0x4D, 0x45, 0x9D, 0x8F, 0x5B, 0x11,
0xC1, 0xC9, 0xE5, 0xCF, 0x45, 0xE5, 0xB1, 0xB3, 0x41, 0xD9,
0xCF, 0xCF
]
key = [0xDE, 0xAD, 0xBE, 0xEF]
s = 0
for i in range(32):
cipher[i] ^= key[i % 4] + i
cipher[i] &= 0xFF
s <<= 8
s += cipher[i]
s <<= 5
s += (s >> (len(bin(s)[2:]) - 5))
s &= ((1 << (32 * 8)) - 1)
from libnum import *
i = 35
flag = [0 for _ in range(32)]
for _ in range(32):
i += -5
i %= 32
print (chr(n2s(s)[i]), end = '')
print ()
VM题真是体力活
[RCTF2019]babyre1
这题其实出的挺好,就是flag的校验差一字节没写好,可惜了
先要输入flag,并长度不能超过 0x10
__printf_chk(1LL, "Input right flag you can got 'Bingo!' :");
__isoc99_scanf("%31s", v11);
v3 = &v11[strlen(v11)];
if ( (unsigned __int64)(v3 - v11) > 0x10 )
{
puts("input is too long!");
}
然后在else里进行的第一个函数中,将16位输入(按照十六进制)压缩成了8个字节,这里还没有要求大小写
中间经过的加解密函数先略过,后面的验证是需要输出一个 Bingo!,要求CRC16的校验结果为0x69E2,然后就会对运算结果再异或 0x17
并输出,程序如下
if ( v4
&& (v5 = sub_180(ptr, v4, &key_202010, 16, &a5), (v6 = v5) != 0LL)
&& a5 > 0
&& CRC16_3D0(v5, a5) == 0x69E2 )
{
for ( i = 0LL; a5 > (int)i; ++i )
v6[i] ^= 0x17u;
puts(v6);
if ( ptr )
free(ptr);
free(v6);
}
在知道运算结果后,看一下中间的运算,核心逻辑为
xxtea_CE0((int *)v8, -(v10 >> 2), a3);
v11 = v8[a2 - 1];
v8[a2] = 0;
*a5 = a2;
if ( a2 > v11 && v11 <= 4 )
{
v13 = a2 - v11;
*a5 = v13;
v8[v13] = 0;
return (char *)v8;
}
就是一个xxtea的程序(其中包括了加密和解密,特征很明显,就不展示了),然后是根据最后一个字节进行字符串的截断
爆破了一下CRC,发现前六个字节正好满足,于是不知道咋办了,查了一下发现后来出题人提供了一个md5,那就写个解密程序然后爆破就行了
[INSHack2017]proprietary-cctv-software
这题用uncompyle6能还原出来源码,是一个PyQt的代码,输入验证部分为
def btn_ok_clicked(self):
s = ''
for le in self.le_parts:
s += le.text()
s += '-'
s = s[:-1]
if self.activator.activate(s.upper()):
self.c.ok.emit()
else:
self.c.ko.emit()
self.close()
以及
class Activator(object):
CHARSET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
def __init__(self):
super(Activator, self).__init__()
self.z = 36
self.checksum = [30, 24, 18, 12, 6, 0]
def block(self, b, mod):
print_dbg('call: block(self, b=<%s>, mod=%d)' % (b, mod))
if len(b) != 6:
print_dbg('err: incorrect block length (%d)' % len(b))
return
s = 0
for k in range(0, len(b)):
l = b[k]
if l not in Activator.CHARSET:
print_dbg('err: input not found in charset (%s)' % l)
return
v = abs(Activator.CHARSET.index(l) - (k + 1))
s += v
print_dbg('current l is: %s' % l)
print_dbg('current k is: %d' % k)
print_dbg('current value is: %d' % v)
print_dbg('current sum is: %d' % s)
return s % mod
def activate(self, s):
print_dbg('call: activate(self, s=<%s>)' % s)
blocks = s.split('-')
blocks_sz = len(blocks)
if blocks_sz != 6:
print_dbg('err: incorrect number of blocks (%d)' % blocks_sz)
return False
for k in range(0, blocks_sz):
self.z = self.block(blocks[k], self.z)
print_dbg('dbg: new z is: %d' % self.z)
if self.z is None:
print_dbg('err: block function returned error')
return False
if self.z != self.checksum[k]:
print_dbg('err: incorrect checksum (z=%d tested against checksum[%d]=%d)' % (self.z, k, self.checksum[k]))
return False
return True
一个方法是逆向这一部分,然后运行程序,应该就能拿到flag
但懒得配环境了,所以又找了一下flag生成函数
class ActivatedWidget(QWidget):
__doc__ = 'docstring for ActivatedWidget'
def __init__(self):
super(ActivatedWidget, self).__init__()
self.lab_result = None
self.yek = [
5, 202, 234, 95,
76, 173, 96, 10,
232, 7, 146, 79,
111, 147, 145, 13]
self.vei = [
175, 161, 61, 70,
144, 218, 0, 50,
73, 173, 240, 202,
184, 17, 148, 2]
self.cne = [
253, 14, 187, 117,
252, 19, 15, 86,
196, 138, 67, 165,
142, 237, 112, 47,
154, 189, 33, 75,
195, 205, 10, 56,
3, 230, 180, 147,
134, 27, 143, 15,
250, 19, 235, 96,
231, 5, 74, 83,
136, 149, 79, 170,
136, 252, 113, 112,
223, 248, 33, 119,
206, 218, 79, 121,
9, 225, 253, 156,
136, 26, 146, 93,
188, 94, 170, 79,
184, 87, 102, 61,
178, 167, 20, 231,
132, 253, 106, 38,
141, 224, 112, 98,
171, 153, 50, 89,
5, 194, 181, 247,
137, 23, 139, 31,
251, 89, 169, 89,
198, 127, 97, 10,
170, 246, 105, 197,
226, 128, 30, 22]
self.init_ui()
def finalize(self):
clear = ''
buf = self.cne
key = self.yek
iv = self.vei
buf_sz = len(buf)
bsize = 16
for i in range(0, int(buf_sz / bsize)):
for j in range(0, bsize):
c = buf[(i * bsize + j)] ^ key[j] ^ iv[j]
iv[j] = buf[(i * bsize + j)]
buf[i * bsize + j] = c
i = buf[(buf_sz - 1)]
for j in range(0, i):
buf[buf_sz - 1 - j] = 0
for i in range(0, buf_sz):
if buf[i] == 0:
break
clear += chr(buf[i])
return clear
手动将这一段提取出来,然后修改一下,将 return
改成 print
,也能拿到flag
简要记录pycdc的bug
ROT_TWO指令未成功还原
好像是蓝帽杯决赛的时候遇到的问题吧?当时用pycdas手动解的,后来修改了一下pyc文件前几个字节的混淆,用pycdc跑完后发现的问题(可能是混淆没去干净,只还原出了前三个函数,不过正好发现了这个bug)
手动还原的为:
def gen_prime(n_bits):
res = gen_num(n_bits)
while not g.is_prime(res):
b = 1
while b != 0:
res, b = res ^ b, (res & b) << 1
return res
然后用pycdc还原的为:
def gen_prime(n_bits):
res = gen_num(n_bits)
while not g.is_prime(res):
b = 1
while b != 0:
res = res ^ b
b = (res & b) << 1
return res
附上pycdas结果
[Code]
File Name: /somewhere/encrypt.py
Object Name: gen_prime
Arg Count: 1
KW Only Arg Count: 0
Locals: 3
Stack Size: 3
Flags: 0x00000043 (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)
[Names]
'gen_num'
'g'
'is_prime'
[Var Names]
'n_bits'
'res'
'b'
[Free Vars]
[Cell Vars]
[Constants]
None
1
0
[Disassembly]
0 LOAD_GLOBAL 0: gen_num
2 LOAD_FAST 0: n_bits
4 CALL_FUNCTION 1
6 STORE_FAST 1: res
8 SETUP_LOOP 54 (to 64)
10 LOAD_GLOBAL 1: g
12 LOAD_METHOD 2: is_prime
14 LOAD_FAST 1: res
16 CALL_METHOD 1
18 POP_JUMP_IF_TRUE 62
20 LOAD_CONST 1: 1
22 STORE_FAST 2: b
24 SETUP_LOOP 34 (to 60)
26 LOAD_FAST 2: b
28 LOAD_CONST 2: 0
30 COMPARE_OP 3 (!=)
32 POP_JUMP_IF_FALSE 58
34 LOAD_FAST 1: res
36 LOAD_FAST 2: b
38 BINARY_XOR
40 LOAD_FAST 1: res
42 LOAD_FAST 2: b
44 BINARY_AND
46 LOAD_CONST 1: 1
48 BINARY_LSHIFT
50 ROT_TWO
52 STORE_FAST 1: res
54 STORE_FAST 2: b
56 JUMP_ABSOLUTE 26
58 POP_BLOCK
60 JUMP_ABSOLUTE 10
62 POP_BLOCK
64 LOAD_FAST 1: res
66 RETURN_VALUE
'gen_prime'
明显有个 ROT_TWO
后来队友手写了一个demo测试了一下
手写的为
a = a ^ b
b = a | b
和
a, b = a ^ b, a | b
然后pycdc结果都是
a = a ^ b
b = a | b
pycdas结果则是一个有 ROT_TWO
,一个没有,是正确的
if判断后接for循环时出现无限嵌套
在做INSHACK2017那道题的时候,一开始电脑里没装uncompyle6,于是打算拿pycdc解,但运行了一下,发现直接生成了一个2G的文件,要不是SegmentFault了估计还能生成,用pycdas解了一下,感觉没什么问题
pycdc卡住的部分:
def activate(self, s):
print_dbg('call: activate(self, s=<%s>)' % s)
blocks = s.split('-')
blocks_sz = len(blocks)
if blocks_sz != 6:
print_dbg('err: incorrect number of blocks (%d)' % blocks_sz)
return False
:
print_dbg('call: activate(self, s=<%s>)' % s)
blocks = s.split('-')
blocks_sz = len(blocks)
if blocks_sz != 6:
print_dbg('err: incorrect number of blocks (%d)' % blocks_sz)
return False
:
print_dbg('call: activate(self, s=<%s>)' % s)
blocks = s.split('-')
blocks_sz = len(blocks)
if blocks_sz != 6:
print_dbg('err: incorrect number of blocks (%d)' % blocks_sz)
return False
:
print_dbg('call: activate(self, s=<%s>)' % s)
blocks = s.split('-')
blocks_sz = len(blocks)
if blocks_sz != 6:
print_dbg('err: incorrect number of blocks (%d)' % blocks_sz)
return False
:
# 后面就是无限嵌套了
uncompyle6结果
def activate(self, s):
print_dbg('call: activate(self, s=<%s>)' % s)
blocks = s.split('-')
blocks_sz = len(blocks)
if blocks_sz != 6:
print_dbg('err: incorrect number of blocks (%d)' % blocks_sz)
return False
for k in range(0, blocks_sz):
self.z = self.block(blocks[k], self.z)
print_dbg('dbg: new z is: %d' % self.z)
if self.z is None:
print_dbg('err: block function returned error')
return False
if self.z != self.checksum[k]:
print_dbg('err: incorrect checksum (z=%d tested against checksum[%d]=%d)' % (self.z, k, self.checksum[k]))
return False
return True
pycdas结果
[Code]
File Name: src/standalone/cctv_manager_standalone.py
Object Name: activate
Arg Count: 2
KW Only Arg Count: 0
Locals: 5
Stack Size: 7
Flags: 0x00000043 (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)
[Names]
'print_dbg'
'split'
'len'
'range'
'block'
'z'
'checksum'
[Var Names]
'self'
's'
'blocks'
'blocks_sz'
'k'
[Free Vars]
[Cell Vars]
[Constants]
None
'call: activate(self, s=<%s>)'
'-'
6
'err: incorrect number of blocks (%d)'
False
0
'dbg: new z is: %d'
'err: block function returned error'
'err: incorrect checksum (z=%d tested against checksum[%d]=%d)'
True
[Disassembly]
0 LOAD_GLOBAL 0: print_dbg
3 LOAD_CONST 1: 'call: activate(self, s=<%s>)'
6 LOAD_FAST 1: s
9 BINARY_MODULO
10 CALL_FUNCTION 1
13 POP_TOP
14 LOAD_FAST 1: s
17 LOAD_ATTR 1: split
20 LOAD_CONST 2: '-'
23 CALL_FUNCTION 1
26 STORE_FAST 2: blocks
29 LOAD_GLOBAL 2: len
32 LOAD_FAST 2: blocks
35 CALL_FUNCTION 1
38 STORE_FAST 3: blocks_sz
41 LOAD_FAST 3: blocks_sz
44 LOAD_CONST 3: 6
47 COMPARE_OP 3 (!=)
50 POP_JUMP_IF_FALSE 71
53 LOAD_GLOBAL 0: print_dbg
56 LOAD_CONST 4: 'err: incorrect number of blocks (%d)'
59 LOAD_FAST 3: blocks_sz
62 BINARY_MODULO
63 CALL_FUNCTION 1
66 POP_TOP
67 LOAD_CONST 5: False
70 RETURN_VALUE
71 SETUP_LOOP 156 (to 230)
74 LOAD_GLOBAL 3: range
77 LOAD_CONST 6: 0
80 LOAD_FAST 3: blocks_sz
83 CALL_FUNCTION 2
86 GET_ITER
87 FOR_ITER 139 (to 229)
90 STORE_FAST 4: k
93 LOAD_FAST 0: self
96 LOAD_ATTR 4: block
99 LOAD_FAST 2: blocks
102 LOAD_FAST 4: k
105 BINARY_SUBSCR
106 LOAD_FAST 0: self
109 LOAD_ATTR 5: z
112 CALL_FUNCTION 2
115 LOAD_FAST 0: self
118 STORE_ATTR 5: z
121 LOAD_GLOBAL 0: print_dbg
124 LOAD_CONST 7: 'dbg: new z is: %d'
127 LOAD_FAST 0: self
130 LOAD_ATTR 5: z
133 BINARY_MODULO
134 CALL_FUNCTION 1
137 POP_TOP
138 LOAD_FAST 0: self
141 LOAD_ATTR 5: z
144 LOAD_CONST 0: None
147 COMPARE_OP 8 (is)
150 POP_JUMP_IF_FALSE 167
153 LOAD_GLOBAL 0: print_dbg
156 LOAD_CONST 8: 'err: block function returned error'
159 CALL_FUNCTION 1
162 POP_TOP
163 LOAD_CONST 5: False
166 RETURN_VALUE
167 LOAD_FAST 0: self
170 LOAD_ATTR 5: z
173 LOAD_FAST 0: self
176 LOAD_ATTR 6: checksum
179 LOAD_FAST 4: k
182 BINARY_SUBSCR
183 COMPARE_OP 3 (!=)
186 POP_JUMP_IF_FALSE 87
189 LOAD_GLOBAL 0: print_dbg
192 LOAD_CONST 9: 'err: incorrect checksum (z=%d tested against checksum[%d]=%d)'
195 LOAD_FAST 0: self
198 LOAD_ATTR 5: z
201 LOAD_FAST 4: k
204 LOAD_FAST 0: self
207 LOAD_ATTR 6: checksum
210 LOAD_FAST 4: k
213 BINARY_SUBSCR
214 BUILD_TUPLE 3
217 BINARY_MODULO
218 CALL_FUNCTION 1
221 POP_TOP
222 LOAD_CONST 5: False
225 RETURN_VALUE
226 JUMP_ABSOLUTE 87
229 POP_BLOCK
230 LOAD_CONST 10: True
233 RETURN_VALUE
'Activator.activate'
也没看出来什么问题