garden
pyc反编译一下
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
import platform
import sys
import marshal
import types
def check(s):
f = '2(88\x006\x1a\x10\x10\x1aIKIJ+\x1a\x10\x10\x1a\x06'
if len(s) != len(f):
return False
checksum = None
for a, b in zip(f, s):
checksum += ord(b) ^ ord(a) ^ 123
return checksum == 0
if sys.version_info.major != 2 or sys.version_info.minor != 7:
sys.exit('\xe8\xaf\x95\xe8\xaf\x95 Python 2.7.')
if len(sys.argv) != 2:
sys.exit('usage: bronze.pyc <flag>')
flag = sys.argv[1]
if len(flag) >= 32:
print '\xe5\xa4\xaa\xe9\x95\xbf\xe4\xba\x86.'
sys.exit(1)
alphabet = set('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789{}!@#$%+')
for ch in flag:
if ch not in alphabet:
print '\xe4\xb8\x8d\xe5\xaf\xb9.'
sys.exit(1)
continue
if check(flag):
print '\xe5\xb0\xb1\xe6\x98\xaf\xe8\xbf\x99\xe4\xb8\xaa!'
sys.exit(0)
else:
print '\xe6\x90\x9e\xe9\x94\x99\xe4\xba\x86.'
sys.exit(1)
有几个输出的东西不太对劲,不过不影响,应该只是一些提示信息,
关键函数:
下面flag要传进函数中的s,最后要满足checksum为0,
ord()把字符转成ascii或unciode码,这些码都是正数,所以异或完还是正数
所以 要满足和为0,需要每项都是0
所以所以 ord(b) ^ ord(a) ^ 123==0
所以所以所以 b= chr(ord(a) ^ 123)
脚本:
f = '2(88\x006\x1a\x10\x10\x1aIKIJ+\x1a\x10\x10\x1a\x06'
for i in f:
b = chr(ord(i) ^ 123)
print(b, end='')
Analysis
题目本身和题目名字,题目说明一样直白
int __cdecl main(int argc, const char **argv, const char **envp)
{
char Plaintext[3]; // [esp+11h] [ebp-97h] BYREF
_BYTE v5[57]; // [esp+14h] [ebp-94h] BYREF
int v6; // [esp+4Dh] [ebp-5Bh]
char input[64]; // [esp+51h] [ebp-57h] BYREF
char v8[7]; // [esp+91h] [ebp-17h] BYREF
int v9; // [esp+98h] [ebp-10h]
int i; // [esp+9Ch] [ebp-Ch]
__main();
v6 = 0;
memset(v5, 0, 4 * (((Plaintext - v5 + 64) & 0xFFFFFFFC) >> 2));
Plaintext[0] = 67;
Plaintext[1] = -33;
Plaintext[2] = 20;
v5[0] = 3;
v5[1] = 13;
v5[2] = 44;
v5[3] = 9;
v5[4] = 1;
v5[5] = 23;
v5[6] = 23;
v5[7] = 8;
v5[8] = -4;
v5[9] = 43;
v5[10] = -6;
v5[11] = 20;
v5[12] = 23;
v5[13] = -7;
v5[14] = 37;
v5[15] = -11;
v5[16] = 34;
v5[17] = 61;
v5[18] = -50;
v5[19] = 24;
v5[20] = 22;
v5[21] = 10;
qmemcpy(v8, "REVERSE", sizeof(v8));
v9 = strlen(Plaintext);
printf(Format);
scanf("%s", input);
mix(input, v8, v9);
for ( i = 0; i < v9; ++i )
{
if ( input[i] != Plaintext[i] )
{
puts(Buffer);
return 0;
}
}
puts(aFlag);
return 0;
}
从最后的循环判断,推出谁是plaintext明文,
关键是用明文逆mix函数推input
int __cdecl mix(char *input, char *key, int len_P)
{
char v3; // dl
int result; // eax
char v5; // [esp+14h] [ebp-24h]
int n; // [esp+18h] [ebp-20h]
int m; // [esp+1Ch] [ebp-1Ch]
int l; // [esp+20h] [ebp-18h]
size_t k; // [esp+24h] [ebp-14h]
int j; // [esp+28h] [ebp-10h]
int i; // [esp+2Ch] [ebp-Ch]
for ( i = 0; i < len_P; ++i )
input[i] -= 64;
for ( j = 0; j < len_P; ++j )
input[j] -= input[j + 1];
for ( k = 0; k < strlen(key); ++k ) // 密钥变形
key[k] %= 64;
for ( l = 0; l < len_P; ++l )
input[l] += key[l % 7];
for ( m = 0; len_P / 2 > m; ++m ) // 倒序排列
{
v5 = input[m];
input[m] = input[len_P - m - 1];
input[len_P - m - 1] = v5;
}
for ( n = 0; ; ++n ) // 循环a3次
{
result = n;
if ( n >= len_P )
break;
if ( (key[n % 7] & 1) != 0 )
v3 = input[n] + 2;
else
v3 = input[n] + 1;
input[n] = v3;
}
return result;
}
自下而上,写脚本
第一步要使用到密钥,所以先对密钥进行变形
ISCC{REVERSE_IS_NOT_HARD}