赛后复现, 学习学习!
嗯, 主办方很喜欢XXTEA呀0.0

babyre1

题目:babyre1

运行:

Input right flag you can got 'Bingo!' :ssssss
input is too short!

IDA打开, 找到主函数:

分析得:输入密文, 长度为16, 范围0-9, a-z

之后用xxtea解密, 后进行CRC16_CCITT校验, 结果应该等于0x69E2。而后对解密后的前N位异或0x17, 根据提示, 最终应该得到Bingo!。

而xxtea解密中:

v11 = (unsigned __int8)v8[v6 - 1];
v8[v6] = 0;
*v5 = v6;
if ( v6 > v11 && v11 <= 4 )
{
v13 = v6 - v11;
*v5 = v13;
v8[v13] = 0;
return v8;
}

根据解密的最后一个字节的大小N, 把明文倒数第N位用”\0”截断。

那么最后一个字节的大小就应该为2, 即最终应该为“Bingo!xx\x02”, xx未知, 而Bingo!应异或0x17.

可以通过提示:MD5(rctf{your answer}) == 5f8243a662cf71bf31d2b2602638dc1d爆破出来。

而我这里是靠猜的, 也不难猜, \x02很像加密时的padding, 所以猜测XXTEA解密后的明文应该为“Bingo!\x02\x02”(其中Bingo!应为异或0x17后的结果)

则解密脚本如下(XXTEA代码网上抄的0.0):

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdint.h>

using namespace std;

#define DELTA 0x9e3779b9
#define MX (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum ^ y) + (key[(p & 3) ^ e] ^ z)))

void btea(uint32_t *v, int n, uint32_t const key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) /* Coding Part */
{
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do
{
sum += DELTA;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p++)
{
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX;
} while (--rounds);
}
else if (n < -1) /* Decoding Part */
{
n = -n;
rounds = 6 + 52 / n;
sum = rounds * DELTA;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--)
{
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
} while (--rounds);
}
}

void decode(char *cipher)
{
int i = 0;
for(i = 0; i < 8; i++)
{
char chr1 = cipher[i] >> 4 & 0xF;
char chr2 = cipher[i] & 0xF;
if(chr1 < 10)
cout << char(chr1 + 0x30);
else
cout << char(chr1 + 0x61 - 10) ;
if (chr2 < 10)
cout << char(chr2 + 0x30);
else
cout << char(chr2 + 0x61 - 10);
}
}

int main()
{
uint32_t cipher[] = {0, 0};
char cipher1[] = "Bingo!\x02\x02";

int i = 0;
uint32_t key[] = { 0xE0C7E0C7, 0xC6F1D3D7, 0xC6D3C6D3, 0xC4D0D2CE };

for (i = 0; i < 6; i++)
{
cipher1[i] ^= 0x17;
}

memcpy(cipher, cipher1, 8);
btea(cipher, 2, key);


cout << "rctf{";
decode((char *)cipher);
cout << "}";

return 0;
}

得到flag:

rctf{05e8a376e4e0446e}

babyre2

题目:babyre2

程序逻辑:

输入8-16位长account, 8-16位长password, 不超过0x400长度的data, data范围:

(buf[i] <= '/' || buf[i] > '9') && (buf[i] <= '`' || buf[i] > 'f') && (buf[i] <= '@' || buf[i] > 'F') )

后以account作为key, 加密一组常量。

v12 = XXtea_1((__int64)&account, (__int64)&v6);
0xF8u, 0xD4u, 0xD5u, 0xDCu, 0xC9u, 0xDAu, 0xCFu, 0xCEu, 0xD7u, 0xDAu, 0xCFu, 0xD2u, 0xD4u, 0xD5u, 0xC8u, 0x9Au, 0xB1u

password的每一位减去十位和个位, 减去的结果作为下标从data取数据, 得到data2.

for ( i = 0; i < v10; ++i )
{
v11 = a1[i] - (a1[i] % 10 + a1[i] / 10);
if ( v11 >= v6 )
{
v8 = 0;
break;
}
ptr[i] = *(_BYTE *)(v11 + a2);
}

用data2异或0xCC作为key密之前的密文。

for ( j = 0; j < a2; ++j )
*((_BYTE *)&dest + j) ^= 0xCCu;
ptr = XXTEA_2(v6, v7, (__int64)&dest, 16, &dword_204058);

于是直接构造account:’1’*16, data’fd’*256, password任意16位即可

脚本:

from pwn import *
p = process('./babyre2')

p.recvuntil('Please input the account:')
p.send('1'*16)
p.recvuntil('Please input the password:')
p.send('1'*16)
p.recvuntil('Please input the data:')
p.send('fd'*256)
p.interactive()

# print(hex(0x31 ^ 0xCC))

p.s.这题还有时间限制, 调试的时候就很喜欢Time Out!0.0….

DontEatMe

题目:DontEatMe

运行程序:

LiHua is trapped on an isolated island. One day, he caught a fish.
Suddenly, the fish said: "Dont eat me! I am Fish God, if you release me, as return , you have one wish."
Li said : I want to know how to escape from this island.
Fish said:

根据输出找到主函数, 一开始有ZwSetInformationThread反调试:

v70 = GetModuleHandleA("Ntdll");
v71 = GetProcAddress(v70, "ZwSetInformationThread");
v72 = GetCurrentThread();

直接跳过就可以了, 伪随机数生成以一串key, 接下来应该是那个函数应该是Blowfish

 srand(0xDEADBEEF);
.....
do
key[v6++] = rand();
while ( v6 < 8 );
key[0] = 0;
v56 = *(_QWORD *)"fishFISH";
*(_WORD *)&key[1] = *(_WORD *)"fishFISH" ^ *(_WORD *)((char *)&v56 + 1);
*(_WORD *)&key[3] = *(_WORD *)((char *)&v56 + 1) ^ *(_WORD *)((char *)&v56 + 3);
*(_WORD *)&key[5] = WORD1(v56) ^ *(_WORD *)((char *)&v56 + 5);
key[7] = BYTE3(v56) ^ aFishfish[7];
Blowfish((int)&v49);

特征为:

.rdata:000B3118 dword_B3118     dd 243F6A88h            ; DATA XREF: Blowfish+12↑o
.rdata:000B311C dd 85A308D3h
.rdata:000B3120 dd 13198A2Eh
.rdata:000B3124 dd 3707344h
.rdata:000B3128 dd 0A4093822h
.rdata:000B312C dd 299F31D0h
.rdata:000B3130 dd 82EFA98h
.rdata:000B3134 dd 0EC4E6C89h
.rdata:000B3138 dd 452821E6h
.rdata:000B313C dd 38D01377h
.rdata:000B3140 dd 0BE5466CFh
.rdata:000B3144 dd 34E90C6Ch
.rdata:000B3148 dd 0C0AC29B7h
.rdata:000B314C dd 0C97C50DDh
.rdata:000B3150 dd 3F84D5B5h
.rdata:000B3154 dd 0B5470917h
.rdata:000B3158 dd 9216D5D9h
.rdata:000B315C dd 8979FB1Bh

接下来这里, 无论输什么, 运算后v8 = 8。所以else里面那一大串都可以不用看hhh

if ( v8 / 16 <= 0 )
{
v25 = envpa;
}
else
{
v12 = (unsigned __int8 *)(v9 + 2);
.....
}

接下来大一串, 就为了生成一个迷宫

a68 = *(_QWORD *)"DontEatM";
v93 = _byteswap_ushort(aDonteatm[0]);
v94 = _byteswap_ushort(WORD1(a68));
v95 = _byteswap_ushort(aDonteatm[2]);
v96 = _byteswap_ushort(aDonteatm[3]);
v97 = &byte_3F501A;
do
{
*((_WORD *)v97 - 1) ^= v93;
*(_WORD *)v97 ^= v94;
*((_WORD *)v97 + 1) ^= v95;
*((_WORD *)v97 + 2) ^= v96;
v97 += 8;
}
while ( (signed int)v97 < (signed int)&unk_3F503A );
v98 = maze;
v99 = (unsigned __int16 *)&unk_3F5018;
do
{
v100 = *v99;
v101 = 15;
do
{
v102 = (v100 & (1 << v101)) >> v101;
--v101;
*v98 = v102;
++v98;
}
while ( v101 > -1 );
++v99;
}
while ( (signed int)v99 < (signed int)&unk_3F5038 );

大概长这样:

1111111111111111
1000000000111111
1011111110111111
1011111110111111
1011110000000111
1011110111110111
1011110111110111
1011110000110111
1011111110110111
1011111110110111
1000000000110111
1111101111110111
1111100000000111
1111111111111111
1111111111111111
1111111111111111

根据maze和解密后的输入进行check

v103 = *v92;
v104 = 10;
v105 = 0;
v106 = 5;
if ( *v92 )
{
v107 = 160;
while ( 1 )
{
switch ( v103 )
{
case 'a':
--v106;
break;
case 'd':
++v106;
break;
case 's':
++v104;
v107 += 16;
break;
case 'w':
--v104;
v107 -= 16;
break;
default:
break;
}
if ( maze[v107 + v106] == 1 )
break;
v103 = v92[v105++ + 1];
if ( !v103 )
{
if ( v104 == 4 && v106 == 9 && v105 < 17 )
{
printf("Congratulations! Here is your flag: RCTF{%s}", &input);
return 0;
}
break;
}
}
}

直接DFS算出明文:

maze = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
op = "adsw"
num = 10
num1 = 0
x = 5
y = 160
def getop(n):
global num
global x
global y
if n == ord(op[0]):
x -= 1
if n == ord(op[1]):
x += 1
if n == ord(op[2]):
num += 1
y += 16
if n == ord(op[3]):
num -= 1
y -= 16

def recover(n):
global num
global x
global y
if n == ord(op[0]):
x += 1
if n == ord(op[1]):
x -= 1
if n == ord(op[2]):
num -= 1
y -= 16
if n == ord(op[3]):
num += 1
y += 16

ans = [0 for i in range(16)]

def dfs(n):
global num
global num1
global x
global y
if n == 16:
if num == 4 and x == 9:
print("".join(map(chr, ans)))
return 0
else:
return 0

for i in list(map(ord, op)):
getop(i)
ans[n] = i
if maze[x+y] != 1:
dfs(n+1)
recover(i)
return 0

dfs(0)

得到:ddddwwwaaawwwddd

最终解密脚本如下:

from Crypto.Cipher import Blowfish

key = b"\x00\x0F\x1A\x01\x35\x3A\x3B\x20"
Cipher = b"ddddwwwaaawwwddd"

obj = Blowfish.new(key)
plain = obj.encrypt(Cipher)

for i in list(map(hex, list(plain))):
print(i[2:4], end = '')

得flag:
RCTF{db824ef8605c5235b4bbacfa2ff8e087}

crack

题目:crack

第一部分

根据字符串, 找到主要函数:

 v4 = v3;
sub_106E558(v3, 1);
v5 = v4[52];
if ( *(_DWORD *)(v5 - 4) > 1 )
sub_10613E0(*(_DWORD *)(v5 - 12));
v6 = 3 * v4[58];
v7 = (void *)v4[56];
v4[53] = v4[52];
memset(v7, 0, v6);
v8 = *(_DWORD *)(v4[52] - 12); // len(input)
v9 = (_DWORD *)v4[54];
v10 = 0;
v11 = 0;
v12 = 0;
v30 = 0x100758E540Fi64;
v29 = v8;
v28 = v9;
v27 = 0;
if ( v8 <= 0 )
return MessageBoxA(0, "Try Again!", "tip", 0);
do
{
v13 = v4[58]; // 0x200
//
if ( v12 >= v13 ) // 0x200 * 0x200
break;
if ( v12 < 0 || (input = (char *)v4[52], v12 > *((_DWORD *)input - 3)) )// len(input) = *(input-3)
sub_1061560(0x80070057);
v15 = *(unsigned __int16 *)&input[2 * v12];
if ( v15 != '0' && v15 != '1' )
return MessageBoxA(0, "Input no accept!", "tip", 0);
if ( v15 == '1' )
v27 = ++v10;
v16 = v28[v10 + v12 * v13];
v17 = (unsigned int)v30 < v16;
LODWORD(v30) = v30 - v16;
v10 = v27;
v9 = v28;
HIDWORD(v30) -= v17;
if ( v12 > v27 )
{
v11[v4[56]] = v28[v12 + v27 * v13];
v11[v4[56] + 1] = BYTE1(v28[v12 + v27 * v4[58]]);
v11[v4[56] + 2] = BYTE2(v28[v12 + v27 * v4[58]]);
v10 = v27;
v11 += 3;
}
++v12;
}
while ( v12 < v29 );
if ( SHIDWORD(v30) > 0 || v30 >= 0 && (_DWORD)v30 )
return MessageBoxA(0, "Try Again!", "tip", 0);
v18 = (void (__stdcall *)(int *, __int64 *, int))v4[56];
v19 = v4[57];
LODWORD(v30) = -1;
v18(v4, &v30, v19);
if ( (_DWORD)v30 == -1 )
return MessageBoxA(0, "Try Again!", "tip", 0);
v20 = v4[50];
v21 = GdipGetImagePixelFormat(*(_DWORD *)(v20 + 4), &v29);
if ( v21 )
*(_DWORD *)(v20 + 8) = v21;
v22 = v4[50];
v23 = GdipBitmapLockBits(*(_DWORD *)(v22 + 4), v4[49], 7, v29, v4[51]);
if ( v23 )
*(_DWORD *)(v22 + 8) = v23;
memcpy_0(&v9[HIDWORD(v30) + v30 * v4[58]], v32, 4 * v31);
v24 = v4[50];
v25 = GdipBitmapUnlockBits(*(_DWORD *)(v24 + 4), v4[51]);
if ( v25 )
*(_DWORD *)(v24 + 8) = v25;
sub_1062880();
MessageBoxA(0, "You get it!", "tip", 0);
sub_106C00A(1000);
return sub_106C22D(0);
}

这一句限制了输入必须为0 or 1:

if ( v15 != '0' && v15 != '1' )

调试运行过程中, 可知v13 = 0x200:

v13 = v4[58];                               // 0x200                           if ( v12 >= v13 )                           // 0x200 * 0x200
break;

这一部分的逻辑很像之前做过的Bugku里面的

因为静态找不到mountain, 所以只能在动态调试过程中将mountain dump出来, 脚本如下:

import ida_bytes
addr = 0x03A24020
fp = open("data.txt", "wb+")
for i in range(0x200 * 0x200):
fp.write(bytes(ida_bytes.get_dword(addr + i * 4)))
fp.write('\n')
fp.close()

得到:

10256753
15502165
5303425
3
....

动态规划求解:

import numpy
data = open("data.txt", "r")
input = []
line = data.readline()
data_list = []
for i in range(0x200):
tmp = []
for j in range(0x200):
num = list(map(int, line.split()))
tmp.append(num)
line = data.readline()
data_list.append(tmp)
data.close()
data = numpy.array(data_list)

path = [""] * len(data)

for i in range(0, len(data) - 1)[::-1]:
for j in range(i+1):
if data[i+1][j] > data[i+1][j+1]:
t = '0'
max = data[i+1][j]
else:
t = '1'
max = data[i+1][j+1]
path[i] += t
data[i][j] += max

# print(hex(data[0][0][0]))
input = '0'
j = 0
for i in range(0x200 - 1):
input += path[i][j]
if path[i][j] == '1':
j += 1
print(input)
print(len(input))

求得512位输入:

00000000010101000000000111100111111110100111100101001000101010010011101100111101011111111111111111001110111011011000000101110111001111100100011000000000000110001111110100000000001101110111010101011111000101110000011000111001110000000000000000000000011001000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000011100011111110000100111000000000000000000000000000000010000000000000001000001100000000000000101000000000100000010000000000000000010000000000000000000000

第二部分

接着分析这个函数:

v18(v4, &v30, v19);

在动态调试过程中可以将汇编代码转成一个函数进行静态分析:

int __stdcall sub_3B46020(_DWORD *a1, int a2, int a3)
{
int result; // eax
signed int j; // [esp+D0h] [ebp-28Ch]
signed int i; // [esp+DCh] [ebp-280h]
__int64 v6; // [esp+E8h] [ebp-274h]
int v7; // [esp+F0h] [ebp-26Ch]
int v8; // [esp+F4h] [ebp-268h]
int v9; // [esp+F8h] [ebp-264h]
int v10; // [esp+FCh] [ebp-260h]
int v11; // [esp+100h] [ebp-25Ch]
int v12; // [esp+104h] [ebp-258h]
int v13; // [esp+108h] [ebp-254h]
int v14; // [esp+10Ch] [ebp-250h]
int v15; // [esp+110h] [ebp-24Ch]
int v16; // [esp+114h] [ebp-248h]
int v17; // [esp+118h] [ebp-244h]
int v18; // [esp+11Ch] [ebp-240h]
int v19; // [esp+120h] [ebp-23Ch]
int v20; // [esp+124h] [ebp-238h]
int v21; // [esp+2F0h] [ebp-6Ch]
int v22; // [esp+2FCh] [ebp-60h]
int v23; // [esp+308h] [ebp-54h]
int v24; // [esp+314h] [ebp-48h]
int v25; // [esp+320h] [ebp-3Ch]
int v26; // [esp+32Ch] [ebp-30h]
int v27; // [esp+338h] [ebp-24h]
int v28; // [esp+344h] [ebp-18h]
int v29; // [esp+350h] [ebp-Ch]

v29 = a1[53] + 2 * a1[58];
v28 = a1[55] + 12;
v27 = *(_DWORD *)a1[55];
v26 = *(_DWORD *)(a1[55] + 4);
v25 = *(_DWORD *)(a1[55] + 8);
v24 = v28;
v23 = 0;
v22 = 0;
v21 = 0;
v6 = 0i64;
v7 = 0;
v8 = 0;
v9 = 0;
v10 = 0;
v11 = 0;
v12 = 0;
v13 = v29;
v14 = 0;
v15 = 0;
v16 = v27;
v17 = v26;
v18 = v25;
v19 = v28;
v20 = a2;
while ( 1 )
{
result = v23 + a3;
if ( !*(_BYTE *)(v23 + a3) )
return result;
v21 += (*(char *)(v23 + a3) - 48) << v23 % 6;
result = v23 / 6;
if ( v23 % 6 != 5 )
goto LABEL_76;
switch ( v21 )
{
case 0:
v21 = 0;
for ( i = 0; i < 24; ++i )
v21 += (*(char *)(++v23 + a3) - 48) << i;
LODWORD(v6) = v21;
goto LABEL_75;
case 1:
v21 = 0;
for ( j = 0; j < 24; ++j )
v21 += (*(char *)(++v23 + a3) - 48) << j;
HIDWORD(v6) = v21;
goto LABEL_75;
case 2:
LODWORD(v6) = *(unsigned __int16 *)(v29 + 2 * v22++);
LABEL_75:
v21 = 0;
LABEL_76:
++v23;
break;
case 3:
HIDWORD(v6) = v6;
goto LABEL_75;
case 4:
v8 = v7;
goto LABEL_75;
case 5:
if ( (signed int)v6 < 128 )
*((_DWORD *)&v6 + v6) = HIDWORD(v6);
goto LABEL_75;
case 6:
if ( SHIDWORD(v6) < 128 )
LODWORD(v6) = *((_DWORD *)&v6 + HIDWORD(v6));
goto LABEL_75;
case 7:
if ( v7 < 128 )
*((_DWORD *)&v6 + v7) = v8;
goto LABEL_75;
case 8:
if ( v8 < 128 )
v7 = *((_DWORD *)&v6 + v8);
goto LABEL_75;
case 9:
LODWORD(v6) = *(_DWORD *)(v6 + 4 * HIDWORD(v6));
goto LABEL_75;
case 10:
*(_DWORD *)(v6 + 4 * HIDWORD(v6)) = v9;
goto LABEL_75;
case 11:
LODWORD(v6) = HIDWORD(v6) + v6;
goto LABEL_75;
case 12:
LODWORD(v6) = v6 - HIDWORD(v6);
goto LABEL_75;
case 13:
LODWORD(v6) = HIDWORD(v6) * v6;
goto LABEL_75;
case 14:
LODWORD(v6) = (signed int)v6 / SHIDWORD(v6);
goto LABEL_75;
case 15:
LODWORD(v6) = HIDWORD(v6) & v6;
goto LABEL_75;
case 16:
LODWORD(v6) = HIDWORD(v6) | v6;
goto LABEL_75;
case 17:
LODWORD(v6) = HIDWORD(v6) ^ v6;
goto LABEL_75;
case 18:
LODWORD(v6) = (_DWORD)v6 << SBYTE4(v6);
goto LABEL_75;
case 19:
LODWORD(v6) = (signed int)v6 >> SBYTE4(v6);
goto LABEL_75;
case 20:
LODWORD(v6) = (signed int)v6 > SHIDWORD(v6);
goto LABEL_75;
case 21:
LODWORD(v6) = (signed int)v6 < SHIDWORD(v6);
goto LABEL_75;
case 22:
LODWORD(v6) = v6 == HIDWORD(v6);
goto LABEL_75;
case 23:
LODWORD(v6) = v6 != HIDWORD(v6);
goto LABEL_75;
case 24:
LODWORD(v6) = v23;
goto LABEL_75;
case 25:
v23 = v6;
v21 = 0;
break;
case 26:
if ( (_DWORD)v6 )
goto LABEL_75;
v23 = HIDWORD(v6);
v21 = 0;
break;
default:
return result;
}
}
}

大概是个VM, 调试过程中将操作码dump出来, 嗯, 复制粘贴

vm

之后分析VM过程, 写个脚本将过程大致还原一下:

code = '000000010101100100000000000000110000010000010110100000000011000000000000000000001100110000000000110000000000000000000000101000000000000000000000000000000000110000000000010000000000000000000000101000000000111000000000000000000000110000011000110000111000010010110000000000110000000000000000000000101000000000100000000000000000000000110000000000010000000000000000000000101000000000011000000000000000000000110000011000111000110100110000000000011000000000000000000000101000100000111000000000000000000000011000100000100000000000000000000000110100110000000000111000000000000000000000101000000000000000000000000000000000100110100000011000000000000000000000011000100000111000000000000000000000101100100000111111000100001011110000011010100000011011000011000000000000010110100000011000000000000000000000011000110000000000110000000000000000000000101000000000100000000000000000000000110000000000010000000000000000000000101000100000110100000000000000000000011000111000100010110000000000110100000000000000000000101000100000001100000000000000000000011000111000100010110000000000001100000000000000000000101000100000101100000000000000000000011000111000100010110000000000101100000000000000000000101000000000111000000000000000000000100000000000000000000000000000101000100000101100000000000000000000011000110000000000110000000000000000000000101000000000100000000000000000000000110000000000010000000000000000000000101000100000111000000000000000000000011000111000101010100000011011111001000000000000010110100000011000000000000000000000011000110000000000110000000000000000000000101000000000100000000000000000000000110000000000010000000000000000000000101000100000111000000000000000000000011000111000110100110000000000000010000000000000000000101000100000111000000000000000000000011000110000000000110000000000000000000000101000000000100000000000000000000000110000000000010000000000000000000000101000100000011100000000000000000000011000111000100100110000000000100010000000000000000000101000100000000010000000000000000000011000110000000000110000000000000000000000101000000000100000000000000000000000110000000000010000000000000000000000101000100000100010000000000000000000011000111000100010110000000000001000000000000000000000101000100000111000000000000000000000011000110000000000110000000000000000000000101000000000100000000000000000000000110000000000010000000000000000000000101000100000011100000000000000000000011000111000010100100000111000000000000000000000011000100000100000000000000000000000110100110000000000111000000000000000000000101000000000000001110010000000000000100110100000110100000000000000000000011000110000000000001000000000000000000000101000100000111100000000000000000000011000100000000000000000000000000000010100100000001100000000000000000000011000110000000000001000000000000000000000101000100000111100000000000000000000011000100000100000000000000000000000010100100000101100000000000000000000011000110000000000001000000000000000000000101000100000111100000000000000000000011000100000010000000000000000000000010100100000011100000000000000000000011000110000000000001000000000000000000000101000100000111100000000000000000000011000100000110000000000000000000000010100'


opcode = 0
i = 0
j = 0
#LODWORD(x) = r0
#HIDWORD(x) = r1
while i < len(code):
opcode = eval('0b'+ code[i:i+6][::-1])
i += 6
if opcode == 0:
num = eval('0b'+ code[i:i+24][::-1])
print('mov r0, 0x%x'%num)
i += 24
elif opcode == 1:
num = eval('0b'+ code[i:i+24][::-1])
print('mov r1, 0x%x'%num)
i += 24
elif opcode == 2:
print('mov r0, input[%d]'% j)
elif opcode == 3:
print('mov r1, r0')
elif opcode == 4:
print('mov r3, r2')
elif opcode == 5:
print("if r0 < 128:")
print('\tmov x[r0], r1')
elif opcode == 6:
print("if r1 < 128:")
print('\tmov r0, x[r1]')
elif opcode == 7:
print("if r3 < 128:")
print('\tmov x[r2], r3')
elif opcode == 8:
print("if r2 < 128:")
print('\tmov r2, x[r3]')
elif opcode == 9:
print('mov r0, x[4 * r1]')
elif opcode == 0xA:
print('mov x[4 * r1], r4')
elif opcode == 0xB:
print('add r0, r1')
elif opcode == 0xC:
print('sub r0, r1')
elif opcode == 0xD:
print('mul r0, r1')
elif opcode == 0xE:
print('div r0, r1')
elif opcode == 0xF:
print('and r0, r1')
elif opcode == 0x10:
print('or r0, r1')
elif opcode == 0x11:
print('xor r0, r1')
elif opcode == 0x12:
print('shl r0, r1')
elif opcode == 0x13:
print('shr r0, r1')
elif opcode == 0x14:
print('cmp r0, r1')
print('setnle r0')
elif opcode == 0x15:
print('cmp r0, r1')
print('setl r0')
elif opcode == 0x16:
print('cmp r0, r1')
print('setz r0')
elif opcode == 0x17:
print("cmp r0, r1")
print('setnz r0')
elif opcode == 0x18:
print("mov r0, rip")
elif opcode == 0x19:
print("mov rip, r0")
elif opcode == 0x1A:
print("cmp r0, 0")
print('je r1')
else:
print("<unknown>")

得到:

mov r0, 0x26a
mov r1, r0
mov r0, input[0]
cmp r0, 0
je r1
mov r1, 0x30
sub r0, r1
mov r1, r0
mov r0, 0x3
if r0 < 128:
mov x[r0], r1
mov r0, 0x0
mov r1, r0
mov r0, 0x2
if r0 < 128:
mov x[r0], r1
mov r0, 0x7
mov r1, r0
if r1 < 128:
mov r0, x[r1]
mov r1, r0
if r3 < 128:
mov x[r2], r3
shl r0, r1
mov r1, r0
mov r0, 0x3
if r0 < 128:
mov x[r0], r1
mov r0, 0x1
mov r1, r0
mov r0, 0x2
if r0 < 128:
mov x[r0], r1
mov r0, 0x6
mov r1, r0
if r1 < 128:
mov r0, x[r1]
if r3 < 128:
mov x[r2], r3
add r0, r1
mov r1, r0
mov r0, 0x6
if r0 < 128:
mov x[r0], r1
mov r1, 0x7
if r1 < 128:
mov r0, x[r1]
mov r1, 0x1
add r0, r1
mov r1, r0
mov r0, 0x7
if r0 < 128:
mov x[r0], r1
mov r0, 0x0
mov rip, r0
mov r1, 0x6
if r1 < 128:
mov r0, x[r1]
mov r1, 0x7
mul r0, r1
mov r1, 0xf423f
cmp r0, r1
setz r0
mov r1, 0xc36
cmp r0, 0
je r1
.....

接下来就只能靠猜的了0.0

由于又这几句:

mov r1, 0x7
mul r0, r1
mov r1, 0xf423f
cmp r0, r1
setz r0
mov r1, 0xc36
cmp r0, 0
je r1

猜测这里是check, 也就是说有另外一个数(暂时不知道这个数怎么算出来的), 这个数*7 == 0xf423f, 也就是0x22e09。又因为整一个逻辑下来只有一句shl r0, r1, 所以猜测有另外一个二进制数跟在前512的输入之后, 而这个二进制数应该为‭100010111000001001‬(==0x22e09)而且输入应该是大端序, 也就是100100000111010001, 即整个第二部分逻辑大概是

input = "100100000111010001"
sum = 0
for i in range(len(input)):
sum += (ord(input) - 0x30) << i
if sum*7 == 0xf423f:
print("sucess")

所以整个输入为前512位输出接上100100000111010001:

00000000010101000000000111100111111110100111100101001000101010010011101100111101011111111111111111001110111011011000000101110111001111100100011000000000000110001111110100000000001101110111010101011111000101110000011000111001110000000000000000000000011001000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000011100011111110000100111000000000000000000000000000000010000000000000001000001100000000000000101000000000100000010000000000000000010000000000000000000000100100000111010001

得到flag:13yR01sw3iy1l1n9

flag