不是每个题都有对应的英文,有些只能网上机翻,XXXX,只作了一小部分
hex->bytes->base64
>>> a = '4c6520666c6167206573743a205a6d78685a3374444d473548636b4230587a427558305675517a42454d57354866513d3d'
>>> bytes.fromhex(a)
>>> b'Le flag est: ZmxhZ3tDMG5HckB0XzBuX0VuQzBEMW5HfQ=='
>>> b64decode('ZmxhZ3tDMG5HckB0XzBuX0VuQzBEMW5HfQ==')
>>> b'flag{C0nGr@t_0n_EnC0D1nG}'
这题很坑,quipquip词频的事放到crypto里,看来观念差别很大
T'MOOMQVUXV BMUDMSYMNIQZPFV CV XV YMYYZBVQV OIUCMUD CVS IVFBS, M TM YMXAIZQV XIQUVV QVSSVYWTMUD MF WVX C'FU XMUMQC, M PFVFV VGIPFMUD FU XMSDIQ, PFZ TFZ SVQD M TM BIZS CV NIFGVQUMZT CMUS T'VMF VD CV QVSVQGV CV NQMZSSV, VD M OMDDVS CV TIFDQV M BIQDVYVUD SFQOQZS TVS OQVYZVQS VJOTIQMDVFQS PFZ T'IUD CVXIFGVQD ; WIU UIYWQV CV UMDFQMTZSDVS VFQIOVVUS IUD XQF M FUV OTMZSMUDVQZV. X'VSD T'FU CVS QMQVS YMYYZBVQVS GVUZYVFJ. TV YID CV OMSSV VSD IQUZDAIQKUPFV
好在这东西也能破解法语,只不过破解完了也不认识
L'APPARENCE FANTASMAGORIQUE DE CE MAMMIFERE PONDANT DES OEUFS, A LA MACHOIRE CORNEE RESSEMBLANT AU BEC D'UN CANARD, A QUEUE EVOQUANT UN CASTOR, QUI LUI SERT A LA FOIS DE GOUVERNAIL DANS L'EAU ET DE RESERVE DE GRAISSE, ET A PATTES DE LOUTRE A FORTEMENT SURPRIS LES PREMIERS EXPLORATEURS QUI L'ONT DECOUVERT ; BON NOMBRE DE NATURALISTES EUROPEENS ONT CRU A UNE PLAISANTERIE. C'EST L'UN DES RARES MAMMIFERES VENIMEUX. LE MOT DE PASSE EST ORNITHORYNQUE
后来翻一下,最后一句是:密码是鸭嘴兽 FLAG{ORNITHORYNQUE} (为啥法语也用flag壳而不是法文呢?)
bin->int->bytes->base64->rot13
0011010100110101001100110011000100110110011000110011010001100110001101010011011000110100001110000011011100110011001101110110000100110101001110010011010100111000001101000011000100110111001101110011011000110011001101010011010000110100001101100011011000111000001101100011010000110100001101000011010100110110001101100011011000110110001100100011011001100100001101010011010100110111011000010011010100111000001100110011001000110101001110010011011100110111001101000110010000110100001101000011010000110010001101100011011000110110001100110011001100110010001101100011100000110110001110000011011000110110001101010011000100110011011001000011001101100100
FLAG{3nc0d1ng5_ar3_s000_fun}
5个字符(其中1个大写)2个数字1个符号,关于hashcat的使用
字典用
?u?l?l?l?l?d?d?s
?l?u?l?l?l?d?d?s
?l?l?u?l?l?d?d?s
?l?l?l?u?l?d?d?s
?l?l?l?l?u?d?d?s
hashcat.exe -a 0 c102_hash.txt c102.dict.txt -m 0
#32d1eff909907fa6f5132662e8749334:plyHx22!
另外几个加密的PDF,加密的zip和巨多代码的crypto103都没作
IDA能看到,略
IDA能看到数字,转一下略
像是python的LLVM吧,从后向前手工搓
#!/usr/bin/env python3
import argparse
def parse_args():
parser = argparse.ArgumentParser(description="Can you recover the flag? If you think you got it, send it as positional argument.")
parser.add_argument("flag", metavar="flag", type=str, help="The flag ")
args = parser.parse_args()
return args
def print_flag(flag):
if len(flag) != 26:
print("You got the wrong flag buddy")
return
if flag[10] == 'e':
print("Nope")
elif flag[4] == chr(0x7B) and flag[25] == chr(0x7D):
if flag[0] == 'F':
if flag[23] == 'g':
if flag[16] == chr(0x30) and flag[18] == '0':
print("That's not it")
elif flag[16] == flag[18] and flag[18] == chr(0x33):
if flag[8] == 'j' or flag[3] == 'A':
print("Wrong!")
elif flag[15] == flag[19] == 'r':
if flag[1:5] != 'FLAG':
if flag[8] == chr(0x5F) and flag[5] == 'n' and flag[0xE] == '_':
if flag[2] == 'G' and flag[3] == 'A':
if flag[3] == 'V' and flag[1] == 'F':
if flag[0x30] == 'F' and flag[0x37] == 'w':
if flag[25] == '{' and flag[4] == '}':
if flag[20] == 'Z' and flag[12] == 'Z':
if flag[10] == 'z':
print("Nope")
elif flag[0x30] == 'f':
if flag[20] == 'a' and flag[3] == 'A':
if flag[19] == 'z':
print("Not even close")
else:
print("Wrong")
elif flag[10] == 'Y' and flag[11] == ']':
if flag[20] == 'S' and flag[22] == 'n':
if flag[16] == 'g' or flag[1] == 'f':
print("Wrong")
elif flag[2] == 'A' and flag[3] == 'G':
if flag[9] == flag[0xC] == 't' and flag[24] == '!':
if flag[0xD] == FUNC_00401064() and flag[1] == 'l'.upper() :
eax = int(flag[6])
if eax == 1 and flag[22] == str(eax):
if flag[20] == 'S' and flag[10] == 'j':
print("wrong")
elif eax == eax ^ eax and flag[11] == FUNC_00401000():
twenty_first_char = 6*int(flag[6]) + 5*int(flag[11]) + 4*int(flag[13]) + 3*int(flag[16]) - 16*int(flag[18])
if twenty_first_char == str(int(hex(int('10101',2)),16)):
if flag[7] == 'z' and flag[17] == 'F':
print("Wrong")
elif flag[0xA] == 'h' and flag[21] == str(twenty_first_char):
if flag[7] == 'z' and flag[17] == 'A':
if flag[20] == 'S' and flag[22] == 'N':
print("You're getting close!")
elif flag[7] == 'w' and flag[17] == 'v':
if flag[20] == 'S' and flag[22] == 'N':
print("You were sooooooo close!")
elif flag[20] == 's' and flag[22] == 'n':
print("Good job! You got the flag! ")
elif flag[7] == 'W' and flag[17] == 'V':
print("You capitalized it wrong")
elif flag[0xA] == 'F' or flag[17] == 'A':
if flag[0x0000A].upper() == 'a':
print("You have to tell me how you managed to end up here!")
elif flag[1] == 'X':
print("Wrong")
else:
if flag[1] == 'A':
if flag[4] == chr(0x24) or flag[4] == chr(0x21):
print("Wrong")
elif flag[0:4] == "FLAG":
if flag[4] == '{' or flag[24] == '}':
if flag[5:24] is not None:
print("Sorry...")
else:
print("How did you get here?")
else:
print("Did you take the right path? I don't think so")
elif flag[16] == 'g' or flag[10] == 'f':
if flag[10] == 'e' and flag[12] == 'g':
if flag[13] == 'e':
if flag[4] == 'F' and flag[1] == '!':
print("Not even close")
else:
print("Your on the wrong track")
elif flag[20] == 'a' and flag[15] == chr(0x01):
if flag[20] == 'A'.lower() and flag[3] == 'c':
print("Keep going")
else:
print("Wrong flag")
else:
print("That's not the right flag")
else:
print("That's not the right flag")
else:
print("That's not the right flag")
else:
print("That's not the right flag")
else:
print("That's not the right flag")
else:
print("That's not the right flag")
def FUNC_00401000():
function_name = 'FUNC_0040'
offset = ''
for i in range(56, 64, 2):
offset = str(i * 3 % 10) + offset
function_name += offset
return globals()[function_name]()
def FUNC_00401064():
with open('flag.py', 'r') as f:
file_length = len(f.read())
return str(int(file_length / 0x458 - 2))
def FUNC_00401128():
return str((0x1 | 0x2 | 0x8) & int('0b1101', 2) & int('0b0111', 2) & int('0b1110', 2))
def FUNC_00402048():
return str(0xF & int('0b1000', 2) & int('0b0001', 2) & int('0b1010', 2))
def FUNC_00402240():
return str((0x3 | 0xC) & int('0b1000', 2) & int('0b0001', 2) & int('0b1010', 2))
def FUNC_00406048():
return str((0x3 | 0xC) & int('0b1101', 2) & int('0b0111', 2) & int('0b1110', 2))
def FUNC_00408046():
return str((0x1 | 0x2 | 0x8) & int('0b1000', 2) & int('0b0001', 2) & int('0b1010', 2))
def FUNC_00409032():
return str((0xF) & int('0b0000', 2) & int('0b0000', 2) | int('0b1111', 2))
def FUNC_00409500():
return str((0x3 | 0xC) & int('0b1001', 2) | int('0b1111', 2) & int('0b0000', 2))
def FUNC_00409999():
return str((0x1 | 0x8) & int('0b1101', 2) & int('0b0111', 2) & int('0b1110', 2))
if __name__ == "__main__":
arguments = parse_args()
print_flag(arguments.flag)
里边很多叉路,手工一点点搓
flag[4] == chr(0x7B) and flag[25] == chr(0x7D)
flag[0] == 'F'
flag[23] == 'g'
flag[16] == flag[18] and flag[18] == chr(0x33)
flag[15] == flag[19] == 'r'
flag[8] == chr(0x5F) and flag[5] == 'n' and flag[0xE] == '_'
flag[2] == 'A' and flag[3] == 'G'
flag[9] == flag[0xC] == 't' and flag[24] == '!'
flag[0xD] == FUNC_00401064() and flag[1] == 'l'.upper() 5
int(flag[6]) == 0
flag[11] == FUNC_00401000() 6048: 4
twenty_first_char = 6*int(flag[6]) + 5*int(flag[11]) + 4*int(flag[13]) + 3*int(flag[16]) - 16*int(flag[18])
flag[0xA] == 'h' and flag[21] == str(twenty_first_char) 1
flag[7] == 'w' and flag[17] == 'v'
flag[20] == 's' and flag[22] == 'n'
FLAG{n0w_th4t5_r3v3rs1ng!}
offset = ''
for i in range(56, 64, 2):
offset = str(i * 3 % 10) + offset
#6048
图片作为密钥文件,怎么出来的不清楚,把exit 给nop掉,gdb跟进去看
int __cdecl main(int argc, const char **argv, const char **envp)
{
size_t rowbytes; // rax
__int64 info_struct; // [rsp+18h] [rbp-48h] BYREF
__int64 v6; // [rsp+20h] [rbp-40h] BYREF
char v7; // [rsp+2Fh] [rbp-31h]
int image_height; // [rsp+30h] [rbp-30h]
int image_width; // [rsp+34h] [rbp-2Ch]
FILE *stream; // [rsp+38h] [rbp-28h]
_QWORD *v11; // [rsp+40h] [rbp-20h]
int j; // [rsp+48h] [rbp-18h]
int i; // [rsp+4Ch] [rbp-14h]
v11 = 0LL;
if ( argc <= 1 )
{
puts("Missing argument");
exit(1);
}
if ( strlen(argv[1]) != 38 )
{
puts("Invalid length");
exit(1);
}
stream = fopen("image.png", "rb");
v6 = png_create_read_struct("1.6.38", 0LL, 0LL, 0LL);
info_struct = png_create_info_struct(v6);
png_init_io(v6, stream);
png_read_info(v6, info_struct);
image_width = png_get_image_width(v6, info_struct);
image_height = png_get_image_height(v6, info_struct);
png_read_update_info(v6, info_struct);
v11 = malloc(8LL * image_height);
for ( i = 0; i < image_height; ++i )
{
rowbytes = png_get_rowbytes(v6, info_struct);
v11[i] = malloc(rowbytes);
}
png_read_image(v6, v11);
for ( j = 0; j <= 37; ++j )
{
v7 = *(_BYTE *)(*v11 + 4 * j) ^ *(_BYTE *)(v11[1] + 4 * j);
if ( v7 != argv[1][j] )
{
puts("Wrong flag...");
exit(1); //把这里干掉,在比较处下断点
}
}
fclose(stream);
png_destroy_read_struct(&v6, &info_struct, 0LL);
puts("Your flag is correct!");
return 0;
}
这回用当前执行的文件名作key,一样的跟
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s1[208]; // [rsp+10h] [rbp-1C0h] BYREF
char v5[192]; // [rsp+E0h] [rbp-F0h] BYREF
__int64 v6[2]; // [rsp+1A0h] [rbp-30h] BYREF
char v7[24]; // [rsp+1B0h] [rbp-20h] BYREF
char *v8; // [rsp+1C8h] [rbp-8h]
v6[0] = 0xEE8BA6DA87759523LL;
v6[1] = 0x651D0881662A99E5LL;
if ( argc <= 1 )
exit(1);
if ( !validate(argv[1]) ) // len =37
exit(2);
decode_key((__int64)v7);
v8 = strrchr(*argv, '/');
decode_ciphertext(v8 + 1, &encoded, s1); // xor
AES_init_ctx_iv(v5, v7, v6);
AES_CTR_xcrypt_buffer(v5, s1, 37LL);
if ( !strcmp(s1, argv[1]) )
puts("Your flag is correct!");
else
puts("Wrong flag...");
return 0;
}
这是拿啥写的程序,一段段目录串,找到对比位置
__int64 __fastcall validatePassword__nimcoded_4(__int64 *a1)
{
char v2[8]; // [rsp+10h] [rbp-40h] BYREF
const char *v3; // [rsp+18h] [rbp-38h]
__int64 v4; // [rsp+20h] [rbp-30h]
const char *v5; // [rsp+28h] [rbp-28h]
__int16 v6; // [rsp+30h] [rbp-20h]
__int64 *v7; // [rsp+48h] [rbp-8h]
v3 = "validatePassword";
v5 = "/kek/src/nimcoded.nim";
v4 = 0LL;
v6 = 0;
nimFrame_4(v2);
v4 = 6LL;
v5 = "/kek/src/nimcoded.nim";
v7 = 0LL;
v7 = encode__pureZbase5452_42(a1, 0);
if ( (unsigned __int8)eqStrings(v7, TM__Lkt3WP7X9a2MvrAhbOYd04Q_4) != 1 )// 相同
{
v4 = 9LL;
v5 = "/kek/src/nimcoded.nim";
echoBinSafe(&TM__Lkt3WP7X9a2MvrAhbOYd04Q_7, 1LL);
}
else
{
v4 = 7LL;
v5 = "/kek/src/nimcoded.nim";
echoBinSafe(&TM__Lkt3WP7X9a2MvrAhbOYd04Q_5, 1LL);
}
return popFrame_4();
}
TM__Lkt3WP7X9a2MvrAhbOYd04Q_4 是个字符串对象,有个头,去掉后是flag,直接在010也能找着
>>> a = 'RkxBR3tIMUREM05fMU5fUEw0MU5fUzFHSFR9'
>>> b64decode(a)
b'FLAG{H1DD3N_1N_PL41N_S1GHT}'
jadx打开,先看AndroidManifest.xml,找到入口com.ettic.sagezone.LoginActivity 打开就看着了
同样找到com.ettic.catchme.LoginActivity发现他调用的jni
public class LoginActivity extends e {
/* renamed from: n reason: collision with root package name */
public static final /* synthetic */ int f1796n = 0;
static {
System.loadLibrary("catchme-native-lib");
}
public native String getValidPassword();
public void goToMainActivity(View view) {
startActivity(new Intent(this, MainActivity.class));
}
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView((int) R.layout.activity_login);
((Button) findViewById(R.id.button)).setOnClickListener(new a(this, (EditText) findViewById(R.id.editTextPassword)));
}
}
把.apk加上.zip解出内置的库,IDA打开
__int64 __fastcall Java_com_ettic_catchme_LoginActivity_getValidPassword(__int64 a1)
{
return (*(__int64 (__fastcall **)(__int64, const char *))(*(_QWORD *)a1 + 1336LL))(
a1,
"FINCTF{NATIV3_C0DE_IS_N0T_SAF3_T00}");
}
题目提示里有base64的密文:X/Is9ULhqsfnEMuZFxv9wBxuU6WQ1FuF+D2ZwPFilwQ=
这个调用了com.ettic.cipherguard.utils.Crypto,这里有加密方法AES,和key 直接找个网站解
package com.ettic.cipherguard.utils;
import android.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class Crypto {
private static final String KEY = "noonecanguessthiskeysoitissafehh";
private Crypto() {
}
public static String encrypt(String str) {
String str2 = "AES";
try {
SecretKeySpec secretKeySpec = new SecretKeySpec(KEY.getBytes(), str2);
Cipher instance = Cipher.getInstance(str2);
instance.init(1, secretKeySpec);
return Base64.encodeToString(instance.doFinal(str.getBytes()), 0);
} catch (Exception unused) {
return "Une erreur s'est produite";
}
}
}
也是APK里的jni 加密有点复杂,都是xmm的指令,不过仔细看非常简单,就是异或
__int64 __fastcall Java_com_ettic_unchained_SecretActivity_getFl0g(__int64 a1)
{
int v2; // eax
int v3; // r15d
const char *v4; // rax
const char *v5; // r13
__int64 v6; // rbx
__int64 v7; // rbp
unsigned int v8; // eax
__int64 v9; // rcx
unsigned __int64 i; // rdx
__int64 v11; // rdi
__m128 v12; // xmm2
unsigned __int64 j; // rdx
__int64 v14; // rdi
__m128 v15; // xmm2
unsigned __int64 k; // rdx
__int64 v17; // rdi
__m128 v18; // xmm2
unsigned __int64 v19; // rdx
__int64 v20; // rdi
__m128 v21; // xmm2
__int64 m; // rdx
__int64 v23; // rax
__int64 v24; // rsi
__m128 v25; // xmm2
char nptr[2]; // [rsp+Dh] [rbp-8Bh] BYREF
char v28; // [rsp+Fh] [rbp-89h]
_WORD v29[40]; // [rsp+10h] [rbp-88h] BYREF
unsigned __int64 v30; // [rsp+60h] [rbp-38h]
v30 = __readfsqword(0x28u);
strcpy(v29, "0c0304091e0c310b0909791919151a187a1e79091e790e150905071a050479041e1937");
v2 = __strlen_chk(v29, 71LL);
v3 = v2;
if ( (v2 & 1) != 0 || (v4 = malloc(v2 / 2 + 1)) == 0LL )
{
fwrite("Oups\n", 5uLL, 1uLL, stderr);
exit(1);
}
v5 = v4;
v6 = 0LL;
if ( v3 > 0 )
{
v7 = 0LL;
do
{
*nptr = v29[v7];
v28 = 0;
v5[v7++] = strtol(nptr, 0LL, 16);
LODWORD(v6) = v6 + 2;
}
while ( v6 < v3 );
v6 = v7;
}
v5[v6] = 0;
v8 = strlen(v5); // v8=35
if ( v8 <= 0 )
return (*(*a1 + 1336LL))(a1, v5);
v9 = v8;
if ( v8 <= 0x1FuLL )
{
for ( i = 0LL; i != v8; v5[i++] ^= 0x58u )
LABEL_13:
;
goto LABEL_14;
}
i = v8 - (v8 & 0x1F); // 35-3
v11 = 0LL;
do
{
v12 = _mm_xor_ps(*&v5[v11 + 16], xmmword_C10);// 58
*&v5[v11] = _mm_xor_ps(*&v5[v11], xmmword_C10);
*&v5[v11 + 16] = v12;
v11 += 32LL;
}
while ( i != v11 );
if ( (v8 & 0x1F) != 0 )
goto LABEL_13;
LABEL_14:
if ( v8 <= 0x1FuLL )
{
for ( j = 0LL; j != v8; v5[j++] ^= 0x50u )
LABEL_19:
;
goto LABEL_20;
}
j = v8 - (v8 & 0x1F);
v14 = 0LL;
do
{
v15 = _mm_xor_ps(*&v5[v14 + 16], xmmword_C20);// \x50
*&v5[v14] = _mm_xor_ps(*&v5[v14], xmmword_C20);
*&v5[v14 + 16] = v15;
v14 += 32LL;
}
while ( j != v14 );
if ( (v8 & 0x1F) != 0 )
goto LABEL_19;
LABEL_20:
if ( v8 <= 0x1FuLL )
{
for ( k = 0LL; k != v8; v5[k++] ^= 0x54u )
LABEL_25:
;
goto LABEL_26;
}
k = v8 - (v8 & 0x1F);
v17 = 0LL;
do
{
v18 = _mm_xor_ps(*&v5[v17 + 16], xmmword_C30);// 54
*&v5[v17] = _mm_xor_ps(*&v5[v17], xmmword_C30);
*&v5[v17 + 16] = v18;
v17 += 32LL;
}
while ( k != v17 );
if ( (v8 & 0x1F) != 0 )
goto LABEL_25;
LABEL_26:
if ( v8 > 0x1FuLL )
{
v19 = v8 - (v8 & 0x1F);
v20 = 0LL;
do
{
v21 = _mm_xor_ps(*&v5[v20 + 16], xmmword_C40);// 44
*&v5[v20] = _mm_xor_ps(*&v5[v20], xmmword_C40);
*&v5[v20 + 16] = v21;
v20 += 32LL;
}
while ( v19 != v20 );
if ( (v8 & 0x1F) == 0 )
goto LABEL_32;
}
else
{
v19 = 0LL;
}
do
v5[v19++] ^= 0x44u;
while ( v8 != v19 );
LABEL_32:
if ( v8 <= 0x1FuLL )
{
for ( m = 0LL; m != v9; ++m )
LABEL_37:
v5[m] ^= 0x52u;
return (*(*a1 + 1336LL))(a1, v5);
}
v23 = v8 & 0x1F;
m = v9 - v23;
v24 = 0LL;
do
{
v25 = _mm_xor_ps(*&v5[v24 + 16], xmmword_C50);// 25
*&v5[v24] = _mm_xor_ps(*&v5[v24], xmmword_C50);
*&v5[v24 + 16] = v25;
v24 += 32LL;
}
while ( m != v24 );
if ( v23 )
goto LABEL_37;
return (*(*a1 + 1336LL))(a1, v5);
}
a = list(bytes.fromhex('0c0304091e0c310b0909791919151a187a1e79091e790e150905071a050479041e1937'))
for i in range(35):
a[i]^=(0x58^0x50^0x54^0x44^0x52)
print(bytes(a))
#b'FINCTF{ACC3SS_PR0T3CT3D_COMPON3NTS}'
一个png文件,通过观察发现每字符高4位被加密,因为PNG文件有固定的头和chunk头的4字符,根据这些字符猜出加密方式是高4个加3
解密后在哈里的脑门上有flag
from pwn import xor
msg = open('on_my_way_to_hogwarts.png','rb').read()
d = [(i+3)%0x10 for i in range(0x10)]
#高位-3
dec = [d[v>>4]*0x10+(v&0xf) for v in msg]
open('on_my2.png', 'wb').write(bytes(dec))
#flag-YerAHackerHarry
#FLAG-YerAHackerHarry
pwn题都没有远端,在国内就都是逆向了,IDA能看到略
同上
打开看到一堆数,直接转bytes
bytes([102,108,97,103,45,109,111,115,116,95,77,117,103,103,108,101,115,95,97,114,101,110,39,116,95,101,120,97,99,116,108,121,95,97,99,99,117,115,116,111,109,101,100,95,116,111,95,115,101,101,105,110,103,95,97,95,102,108,121,105,110,103,95,99,97,114])
#flag-most_Muggles_aren't_exactly_accustomed_to_seeing_a_flying_car
一开始没弄明白他要干什么,就能看到ftp登录信息,后来才知道让输入密码
Pouvez-vous retrouver le mot de passe utilisé pour se connecter à ce serveur FTP ?
Format : FLAG {flag-ici}