前言
本人作为RE出题人之一,本次校赛出了2道原创题,babyida
和magicpyc
。其他都是去年寒假初学RE时做的,在其他文章里面有详细解法。本次我出题确实很烂,没想到有些题太容易就能搜到,以后一定会好好上强度的😈😈😈。
babyida
本来想出个和去年校赛一样的字符串搜索逆向签到题,但是出的时候觉得有点简单了,所以就在处理字符串的开头加入了一段简单的花指令。 本来解法是想让大家搜到假flag然后定位并去花,结果当时没多少人做出来,故在中途加了个提示(本来提示挺温柔的🤗,被cc改了)。 因此本题有2种解法,去花之间出和动调定位flag位置和处理逻辑。
源码
#include <iostream>
#include <string.h>
char fake_flag[100] = "flag{You_think_you_have_found_the_true_flag?}";
void flaghere(char * s) {
std::cout << "Can you find the flag?\n";
__asm {
call LABEL9;
_emit 0x83;
LABEL9:
add dword ptr ss : [esp] , 8;
ret;
__emit 0xF3;
}
char true_flag[100];
true_flag[0] = 102;
true_flag[1] = 108;
true_flag[2] = 97;
true_flag[3] = 103;
true_flag[4] = 123;
true_flag[5] = 49;
true_flag[6] = 78;
true_flag[7] = 116;
true_flag[8] = 52;
true_flag[9] = 114;
true_flag[10] = 52;
true_flag[11] = 115;
true_flag[12] = 116;
true_flag[13] = 49;
true_flag[14] = 110;
true_flag[15] = 103;
true_flag[16] = 95;
true_flag[17] = 49;
true_flag[18] = 100;
true_flag[19] = 48;
true_flag[20] = 95;
true_flag[21] = 115;
true_flag[22] = 101;
true_flag[23] = 48;
true_flag[24] = 114;
true_flag[25] = 99;
true_flag[26] = 104;
true_flag[27] = 95;
true_flag[28] = 49;
true_flag[29] = 115;
true_flag[30] = 78;
true_flag[31] = 116;
true_flag[32] = 95;
true_flag[33] = 49;
true_flag[34] = 84;
true_flag[35] = 125;
true_flag[36] = 0;
for (int i = 0; i < strlen(true_flag); i++) {
if (true_flag[i] >= '0' && true_flag[i] <= '9') {
true_flag[i] = true_flag[i] + 3;
}
}
std::cout << true_flag;
if (!strcmp(s, true_flag)) {
std::cout << "Congratulations!";
}
else {
std::cout << "Wrong!";
}
if (!strcmp(s, fake_flag)) {
std::cout << "HAHAHA,YOU ARE WRONG!";
}
system("pause");
}
int main()
{
char s[100];
std::cout << "Please input the final flag:";
std::cin >> s;
flaghere(s);
//flag{4Nt7r7st4ng_4d3_se3rch_4sNt_4T}
}
去花
找到函数jumpout的位置,观察汇编text视图,找到花指令的位置,nop掉所有无关的跳转。本题花指令通过增加esp达到跳转到返回地址后几字节位置的效果。
动调
程序没有反调试,直接在函数下断点并步入,一步一步运行即可得到初始flag,继续运行会发现简单的处理逻辑。
magicpyc
本题给出了pyc文件,并给出了python版本的范围。pyc文件是损坏的,这是由于去除了开头16字节的信息,其中包含4字节的magic number和12字节的其他信息,其他信息不影响pyc反编译,填充0即可,magic number可以根据特性尝试出来,版本为python3.8。
源码
import random
def create_playfair_matrix(key):
key = key.replace(" ", "").upper()
alphabet = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
matrix = []
for char in key + alphabet:
if char not in matrix:
matrix.append(char)
return matrix
def prepare_message(message):
message = message.replace(" ", "").upper()
message = message.replace("J", "I")
prepared_message = message[0]
for i in range(1, len(message)):
if message[i] == message[i - 1]:
prepared_message += 'X'
prepared_message += message[i]
if len(prepared_message) % 2 != 0:
prepared_message += 'X'
return prepared_message
def playfair_encrypt(message, key):
matrix = create_playfair_matrix(key)
prepared_message = prepare_message(message)
encrypted_message = ""
for i in range(0, len(prepared_message), 2):
char1, char2 = prepared_message[i], prepared_message[i + 1]
row1, col1 = divmod(matrix.index(char1), 5)
row2, col2 = divmod(matrix.index(char2), 5)
if row1 == row2:
encrypted_message += matrix[row1 * 5 + (col1 + 1) % 5]
encrypted_message += matrix[row2 * 5 + (col2 + 1) % 5]
elif col1 == col2:
encrypted_message += matrix[(row1 + 1) % 5 * 5 + col1]
encrypted_message += matrix[(row2 + 1) % 5 * 5 + col2]
else:
encrypted_message += matrix[row1 * 5 + col2]
encrypted_message += matrix[row2 * 5 + col1]
return encrypted_message
def rot13(text):
encrypted_text = ""
for char in text:
if 'a' <= char <= 'z':
encrypted_char = chr(((ord(char) - ord('a') + 13) % 26) + ord('a'))
elif 'A' <= char <= 'Z':
encrypted_char = chr(((ord(char) - ord('A') + 13) % 26) + ord('A'))
else:
encrypted_char = char
encrypted_text += encrypted_char
return encrypted_text
def vigenere_encrypt(plain_text, key):
key = rot13(key)
encrypted_text = ""
key_length = len(key)
for i in range(len(plain_text)):
char = plain_text[i]
if char.isalpha():
key_char = key[i % key_length]
shift = ord(key_char.lower()) - ord('a')
if char.isupper():
encrypted_char = chr(
((ord(char) - ord('A') + shift) % 26) + ord('A'))
else:
encrypted_char = chr(
((ord(char) - ord('a') + shift) % 26) + ord('a'))
else:
encrypted_char = char
encrypted_text += encrypted_char
return encrypted_text
def grid_encrypto(plain_message):
encrypt_message = ""
mid = len(plain_message)//2
for i in range(mid):
encrypt_message += plain_message[i]
encrypt_message += plain_message[i+mid]
if len(plain_message) % 2:
encrypt_message += plain_message[-1]
return encrypt_message
def encrypt(plain_message, key):
encrypted_message = vigenere_encrypt(plain_message, key)
r = random.randint(10, 20)
for _ in range(r):
encrypted_message = grid_encrypto(encrypted_message)
encrypted_message = encrypted_message[1:]+encrypted_message[0]
return encrypted_message
flag = "flag{M4G1c_nUMb8r_1s_F3n!W4lc0m3ToPyth0nRev3rse!}"
key = "NPUSECWELCOMMMEYOUUU"
key1 = "WHEREISMYKEY"
key2 = playfair_encrypt(key, key1)
print("key2=", key2)
cipher = encrypt(flag, key)
print("cipher=", cipher)
wp
def create_playfair_matrix(key):
key = key.replace(" ", "").upper()
alphabet = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
matrix = []
for char in key + alphabet:
if char not in matrix:
matrix.append(char)
return matrix
def playfair_decrypt(encrypted_message, key):
matrix = create_playfair_matrix(key)
decrypted_message = ""
for i in range(0, len(encrypted_message), 2):
char1, char2 = encrypted_message[i], encrypted_message[i + 1]
row1, col1 = divmod(matrix.index(char1), 5)
row2, col2 = divmod(matrix.index(char2), 5)
if row1 == row2:
decrypted_message += matrix[row1 * 5 + (col1 - 1) % 5]
decrypted_message += matrix[row2 * 5 + (col2 - 1) % 5]
elif col1 == col2:
decrypted_message += matrix[(row1 - 1) % 5 * 5 + col1]
decrypted_message += matrix[(row2 - 1) % 5 * 5 + col2]
else:
decrypted_message += matrix[row1 * 5 + col2]
decrypted_message += matrix[row2 * 5 + col1]
decrypted_message = decrypted_message.replace('X', '')
return decrypted_message
def grid_decrypt(encrypted_message):
decrypted_message = ""
length = len(encrypted_message)
for i in range(length):
if i % 2 == 0 and i != length-1:
decrypted_message += encrypted_message[i]
for i in range(length):
if i % 2 == 1:
decrypted_message += encrypted_message[i]
if length % 2:
decrypted_message += encrypted_message[-1]
return decrypted_message
def rot13(text):
encrypted_text = ""
for char in text:
if 'a' <= char <= 'z':
encrypted_char = chr(((ord(char) - ord('a') + 13) % 26) + ord('a'))
elif 'A' <= char <= 'Z':
encrypted_char = chr(((ord(char) - ord('A') + 13) % 26) + ord('A'))
else:
encrypted_char = char
encrypted_text += encrypted_char
return encrypted_text
def vigenere_decrypt(encrypted_text, key):
key = rot13(key)
decrypted_text = ""
key_length = len(key)
for i in range(len(encrypted_text)):
char = encrypted_text[i]
if char.isalpha():
key_char = key[i % key_length]
shift = ord(key_char.lower()) - ord('a')
if char.isupper():
decrypted_char = chr(
((ord(char) - ord('A') - shift + 26) % 26) + ord('A'))
else:
decrypted_char = chr(
((ord(char) - ord('a') - shift + 26) % 26) + ord('a'))
else:
decrypted_char = char
decrypted_text += decrypted_char
return decrypted_text
def decrypt(encrypted_message, key, r):
for _ in range(r):
encrypted_message = encrypted_message[-1] + encrypted_message[:-1]
encrypted_message = grid_decrypt(encrypted_message)
plain_message = vigenere_decrypt(encrypted_message, key)
return plain_message
key1 = "WHEREISMYKEY"
key2 = "OQTMHDHRNBNYUKUKYDNVZVZV"
key = playfair_decrypt(key2, key1)
cipher ="4n30nac1L1luRjsLn8_B!!oSc3_hXhiTu0}zsr{n_f34GsgHm"# "gn1830f3l__}30uBhz4nR!XsHaj!hrscsoi{m1LSTn4Lncu_G"
for r in range(10, 20):
flag = decrypt(cipher, key, r)
if "flag{" in flag:
print(f"r={r}: {flag}")