questionCTF week3 wp – b0t
re1 BrokenData
根据提示input[10]要么是y要么是Y,都试一下
以Y举例
dump下
key1:
0xA0,0x6A,0x8E,0x86,0x42,0x3C,0x9E,0x27,0x23,0x52,0x7B,0xDA,0x51,0x8D,0x97,0x27
key2:
0x4D,0x71,0x79,0x67,0x80,0xA1,0xF1,0x24,0x27,0x8C,0x8B,0x7C,0x2B,0xB1,0x7D,0x84
Buf1[208] = {
0x81,0x6D,0xF2,0xDA,0x3B,0x09,0xCF,0x85,0xBC,0x3F,0xDC,0x25,0xED,0x45,0x52,0xAF,
0x3A,0xDD,0x51,0x69,0x6B,0x5E,0x97,0x2E,0xF6,0xF4,0x2B,0x3F,0xC9,0x01,0xBC,0xFB,
0xD1,0xA5,0x58,0x8E,0x1F,0xE6,0xB8,0x36,0xA7,0x1E,0xA1,0x9D,0x3E,0x42,0x52,0x6C,
0x91,0xFD,0xDE,0xDC,0x1B,0xD2,0x88,0x3C,0x89,0x48,0x19,0x57,0x2F,0x30,0x03,0x3D,
0x02,0x32,0x8E,0xFC,0x3C,0x5B,0x8A,0x47,0xCA,0xB4,0x3E,0xD3,0x8E,0x05,0x5D,0xCD,
0x8D,0xE7,0xFC,0x29,0xCA,0xBA,0xDE,0x9E,0x6C,0x3B,0x96,0x92,0x0B,0x54,0x7F,0xC6,
0x71,0x4D,0x2A,0x82,0x8F,0x42,0x0C,0x54,0x2C,0x84,0xF8,0x67,0x34,0x7E,0xC8,0x77,
0xE1,0x1B,0x7F,0xDB,0x8B,0x87,0x97,0x01,0x01,0x63,0x14,0x05,0x4D,0xBF,0xCC,0x10,
0x52,0x49,0x87,0xBC,0x5E,0x16,0xEA,0x0F,0x7D,0xF5,0x75,0x8D,0x05,0xB0,0x43,0xF2,
0x57,0xFD,0x7E,0x40,0xFE,0xB4,0x5C,0xA8,0xC0,0x63,0x8B,0x08,0x80,0xE6,0x2B,0x4D,
0x41,0x77,0x71,0x07,0xFC,0x71,0xFE,0x21,0x77,0x07,0x8B,0xE2,0x7D,0x9E,0xB6,0x04,
0x64,0x0D,0xBD,0xE1,0x59,0x10,0x5F,0xA7,0x80,0x08,0xAB,0x96,0x3C,0x34,0xC6,0xBB,
0x81,0x0D,0xE4,0xFA,0x53,0x99,0x22,0xC1,0xC9,0xA7,0xE9,0x39,0x75,0x10,0xDA,0xA4
};
再分析enc函数,跟进enc
void __fastcall enc(char *input, char *key, char *output)
{
char v3; // al
int j; // [rsp+30h] [rbp-48h]
int i; // [rsp+34h] [rbp-44h]
int v6; // [rsp+38h] [rbp-40h]
int j_1; // [rsp+3Ch] [rbp-3Ch]
__int64 bufa[2]; // [rsp+40h] [rbp-38h] BYREF
v6 = 0;
for ( i = 0; i < 13; ++i )
{
j_1 = dword_7FF6CCFD6180[i];
memset(bufa, 0, sizeof(bufa));
for ( j = 0; j < 16; ++j )
{
if ( j >= j_1 )
v3 = input[5];
else
v3 = input[j + v6];
*((_BYTE *)bufa + j) = v3;
}
if ( i % 2 )
sub_7FF6CCFD1AA0(key, 0x10u, (__int64)bufa, (__int64)bufa, 0x10u);
else
sub_7FF6CCFD1AA0(key + 16, 0x10u, (__int64)bufa, (__int64)bufa, 0x10u);
qmemcpy(&output[16 * i], bufa, 0x10uLL);
v6 += j_1;
}
}
首先for循环这一段是对56字节加密数据进行填充,挺奇特的填充方式
每一块是16字节,根据dword_7FF6CCFD6180块索引得出的值是原始数据的字节数,每一块赋值dword_7FF6CCFD6180[i]个字节后用input[5]填充
填充完的原文有13x16 = 208字节,跟密文一样
后面这个if判断的逻辑是奇数块用key2加密,偶数块用key1加密
跟进 sub_7FF6CCFD1AA0
__int64 __fastcall sub_7FF6CCFD1AA0(const void *buf_4, unsigned int n16, __int64 buf, __int64 a4, unsigned int i)
{
unsigned int j; // [rsp+20h] [rbp-1E8h]
int k; // [rsp+24h] [rbp-1E4h]
_BYTE *v8; // [rsp+28h] [rbp-1E0h]
_BYTE buf_1[16]; // [rsp+38h] [rbp-1D0h] BYREF
_BYTE v11[368]; // [rsp+50h] [rbp-1B8h] BYREF
_BYTE buf_3[16]; // [rsp+1C0h] [rbp-48h] BYREF
_BYTE buf_2[16]; // [rsp+1D0h] [rbp-38h] BYREF
v8 = v11;
memset(buf_1, 0, sizeof(buf_1));
memset(buf_2, 0, sizeof(buf_2));
memset(buf_3, 0, sizeof(buf_3));
qmemcpy(buf_2, buf_4, n16);
sub_7FF6CCFD1100(buf_2, 16LL, v11);
for ( j = 0; j < i; j += 16 )
{
sub_7FF6CCFD1000((__int64)buf_3, (_BYTE *)buf);
sub_7FF6CCFD1490(buf_3, v11);
for ( k = 1; k < 10; ++k )
{
v8 += 16;
sub_7FF6CCFD1560(buf_3);
sub_7FF6CCFD15E0(buf_3);
sub_7FF6CCFD1860(buf_3);
sub_7FF6CCFD1490(buf_3, v8);
}
sub_7FF6CCFD1560(buf_3);
sub_7FF6CCFD15E0(buf_3);
sub_7FF6CCFD1490(buf_3, v8 + 16);
sub_7FF6CCFD1080(buf_3, a4);
a4 += 16LL;
buf += 16LL;
v8 = v11;
}
return 0LL;
}
跟进sub_7FF6CCFD1100
__int64 __fastcall sub_7FF6CCFD1100(__int64 a1, int n16, _DWORD *a3)
{
int i; // [rsp+0h] [rbp-28h]
int m; // [rsp+4h] [rbp-24h]
int j; // [rsp+8h] [rbp-20h]
int k; // [rsp+Ch] [rbp-1Ch]
_DWORD *v8; // [rsp+10h] [rbp-18h]
_DWORD *v9; // [rsp+10h] [rbp-18h]
_DWORD *v10; // [rsp+18h] [rbp-10h]
if ( !a1 || !a3 )
return 0xFFFFFFFFLL;
if ( n16 != 16 )
return 0xFFFFFFFFLL;
v8 = a3;
v10 = a3 + 44;
for ( i = 0; i < 4; ++i )
a3[i] = _byteswap_ulong(*(_DWORD *)(4 * i + a1));
for ( j = 0; j < 10; ++j )
{
v8[4] = dword_7FF6CCFD4280[j] ^ byte_7FF6CCFD6080[HIBYTE(v8[3])] ^ (unsigned __int16)(byte_7FF6CCFD6080[(unsigned __int8)v8[3]] << 8) ^ (byte_7FF6CCFD6080[BYTE1(v8[3])] << 16) & 0xFF0000 ^ (byte_7FF6CCFD6080[(unsigned __int8)BYTE2(v8[3])] << 24) ^ *v8;
v8[5] = v8[4] ^ v8[1];
v8[6] = v8[5] ^ v8[2];
v8[7] = v8[6] ^ v8[3];
v8 += 4;
}
v9 = a3 + 40;
for ( k = 0; k < 11; ++k )
{
for ( m = 0; m < 4; ++m )
v10[m] = v9[m];
v9 -= 4;
v10 += 4;
}
return 0LL;
}__int64 __fastcall sub_7FF6CCFD1100(__int64 a1, int n16, _DWORD *a3)
{
int i; // [rsp+0h] [rbp-28h]
int m; // [rsp+4h] [rbp-24h]
int j; // [rsp+8h] [rbp-20h]
int k; // [rsp+Ch] [rbp-1Ch]
_DWORD *v8; // [rsp+10h] [rbp-18h]
_DWORD *v9; // [rsp+10h] [rbp-18h]
_DWORD *v10; // [rsp+18h] [rbp-10h]
if ( !a1 || !a3 )
return 0xFFFFFFFFLL;
if ( n16 != 16 )
return 0xFFFFFFFFLL;
v8 = a3;
v10 = a3 + 44;
for ( i = 0; i < 4; ++i )
a3[i] = _byteswap_ulong(*(_DWORD *)(4 * i + a1));
for ( j = 0; j < 10; ++j )
{
v8[4] = dword_7FF6CCFD4280[j] ^ c[HIBYTE(v8[3])] ^ (unsigned __int16)(byte_7FF6CCFD6080[(unsigned __int8)v8[3]] << 8) ^ (byte_7FF6CCFD6080[BYTE1(v8[3])] << 16) & 0xFF0000 ^ (byte_7FF6CCFD6080[(unsigned __int8)BYTE2(v8[3])] << 24) ^ *v8;
v8[5] = v8[4] ^ v8[1];
v8[6] = v8[5] ^ v8[2];
v8[7] = v8[6] ^ v8[3];
v8 += 4;
}
v9 = a3 + 40;
for ( k = 0; k < 11; ++k )
{
for ( m = 0; m < 4; ++m )
v10[m] = v9[m];
v9 -= 4;
v10 += 4;
}
return 0LL;
}
查看byte_7FF6CCFD6080

很标准的AES的S盒
再跟进dword_7FF6CCFD4280也是标准的rcon
猜测是AES加密,奇偶块用的密钥不同
可以直接用赛博厨子梭出来,手动去除填充

也可以直接写脚本解密
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <openssl/md5.h>
#include <openssl/aes.h>
#include <stdlib.h>
static const uint8_t Buf1[208] = {
0x81,0x6D,0xF2,0xDA,0x3B,0x09,0xCF,0x85,0xBC,0x3F,0xDC,0x25,0xED,0x45,0x52,0xAF,
0x3A,0xDD,0x51,0x69,0x6B,0x5E,0x97,0x2E,0xF6,0xF4,0x2B,0x3F,0xC9,0x01,0xBC,0xFB,
0xD1,0xA5,0x58,0x8E,0x1F,0xE6,0xB8,0x36,0xA7,0x1E,0xA1,0x9D,0x3E,0x42,0x52,0x6C,
0x91,0xFD,0xDE,0xDC,0x1B,0xD2,0x88,0x3C,0x89,0x48,0x19,0x57,0x2F,0x30,0x03,0x3D,
0x02,0x32,0x8E,0xFC,0x3C,0x5B,0x8A,0x47,0xCA,0xB4,0x3E,0xD3,0x8E,0x05,0x5D,0xCD,
0x8D,0xE7,0xFC,0x29,0xCA,0xBA,0xDE,0x9E,0x6C,0x3B,0x96,0x92,0x0B,0x54,0x7F,0xC6,
0x71,0x4D,0x2A,0x82,0x8F,0x42,0x0C,0x54,0x2C,0x84,0xF8,0x67,0x34,0x7E,0xC8,0x77,
0xE1,0x1B,0x7F,0xDB,0x8B,0x87,0x97,0x01,0x01,0x63,0x14,0x05,0x4D,0xBF,0xCC,0x10,
0x52,0x49,0x87,0xBC,0x5E,0x16,0xEA,0x0F,0x7D,0xF5,0x75,0x8D,0x05,0xB0,0x43,0xF2,
0x57,0xFD,0x7E,0x40,0xFE,0xB4,0x5C,0xA8,0xC0,0x63,0x8B,0x08,0x80,0xE6,0x2B,0x4D,
0x41,0x77,0x71,0x07,0xFC,0x71,0xFE,0x21,0x77,0x07,0x8B,0xE2,0x7D,0x9E,0xB6,0x04,
0x64,0x0D,0xBD,0xE1,0x59,0x10,0x5F,0xA7,0x80,0x08,0xAB,0x96,0x3C,0x34,0xC6,0xBB,
0x81,0x0D,0xE4,0xFA,0x53,0x99,0x22,0xC1,0xC9,0xA7,0xE9,0x39,0x75,0x10,0xDA,0xA4
};
const int lengths[13] = {1,4,6,9,11,6,3,2,3,1,7,1,2}; // first 13 entries from dword_... (sum == 56)
const char *basekey = "%es_&ou_fou**_ke%"; // 17 bytes
// decrypt one 16-byte block AES-128
void aes_decrypt_block(const uint8_t in[16], uint8_t out[16], const uint8_t key16[16]) {
AES_KEY dec_key;
AES_set_decrypt_key(key16, 128, &dec_key);
AES_decrypt(in, out, &dec_key);
}
// encrypt one 16-byte block AES-128
void aes_encrypt_block(const uint8_t in[16], uint8_t out[16], const uint8_t key16[16]) {
AES_KEY enc_key;
AES_set_encrypt_key(key16, 128, &enc_key);
AES_encrypt(in, out, &enc_key);
}
int try_candidate(char candidate_char) {
uint8_t key1[16], key2[16];
uint8_t md[16];
// key1 = MD5(basekey, 17)
MD5((const unsigned char*)basekey, 17, md);
memcpy(key1, md, 16);
// key2: modified basekey with positions 0,4,16 set to candidate_char, then MD5(...,17)
char keymod[24];
memcpy(keymod, basekey, 17);
keymod[0] = candidate_char;
keymod[4] = candidate_char;
keymod[16] = candidate_char;
MD5((const unsigned char*)keymod, 17, md);
memcpy(key2, md, 16);
// reconstruct input (56 bytes)
unsigned char input[56];
memset(input, 0, sizeof(input));
int v6 = 0;
int seen_input5 = 0;
unsigned char input5 = 0;
// For each block i=0..12
for (int i = 0; i < 13; ++i) {
const uint8_t *cipher_block = Buf1 + 16*i;
uint8_t decblk[16];
// key selection: in original code, if (i % 2) use buf (key1), else use buf+16 (key2)
const uint8_t *use_key = (i % 2) ? key1 : key2;
aes_decrypt_block(cipher_block, decblk, use_key);
int j1 = lengths[i];
// fill input bytes for j < j1, validate filler for j >= j1
for (int j = 0; j < 16; ++j) {
unsigned char v3 = decblk[j];
if (j < j1) {
// should map to input[v6 + j]
int idx = v6 + j;
if (idx >= 0 && idx < 56) {
input[idx] = v3;
} else {
// out of range - fail
return 0;
}
} else {
// should equal input[5]
if (!seen_input5) {
input5 = v3;
seen_input5 = 1;
} else {
if (input5 != v3) {
// inconsistency -> candidate fails
return 0;
}
}
}
}
v6 += j1;
}
if (!seen_input5) {
// no filler observed? unlikely, but fail
return 0;
}
// set input[5]
input[5] = input5;
// At this point we have a filled 56-byte input. Verify by re-encrypting to produce Buf2 and compare with Buf1.
// Reproduce enc() exactly and check Buf2 == Buf1
unsigned char Buf2[208];
memset(Buf2, 0, sizeof(Buf2));
v6 = 0;
for (int i = 0; i < 13; ++i) {
uint8_t bufa[16];
int j1 = lengths[i];
for (int j = 0; j < 16; ++j) {
if (j >= j1) bufa[j] = input[5];
else bufa[j] = input[v6 + j];
}
// encrypt bufa -> outblk
uint8_t outblk[16];
const uint8_t *use_key = (i % 2) ? key1 : key2;
aes_encrypt_block(bufa, outblk, use_key);
// copy to Buf2
memcpy(Buf2 + 16*i, outblk, 16);
v6 += j1;
}
if (memcmp(Buf1, Buf2, sizeof(Buf1)) == 0) {
// success: print recovered input
printf("SUCCESS candidate input[10] = '%c'\n", candidate_char);
printf("Recovered input (56 bytes):\n");
for (int i = 0; i < 56; ++i) {
unsigned char c = input[i];
// print printable or hex escape
if (c >= 0x20 && c < 0x7f) putchar(c);
else printf("\\x%02X", c);
}
putchar('\n');
// also print hex
printf("Hex: ");
for (int i = 0; i < 56; ++i) printf("%02X ", input[i]);
printf("\n");
return 1;
} else {
// mismatch
return 0;
}
}
int main(void) {
char candidates[2] = {'y','Y'};
int found = 0;
for (int k = 0; k < 2; ++k) {
if (try_candidate(candidates[k])) {
found = 1;
break;
} else {
printf("candidate '%c' failed.\n", candidates[k]);
}
}
if (!found) {
printf("No candidate succeeded. You can try other possible input[10] bytes by modifying the code.\n");
}
return 0;
}
编译:gcc -std=c11 -O2 decScript.c -o decScript -lcrypto
运行:./decScript
flag{Wow!_You_restored_the_data_and_this_is_your_reward}
re2 Fisher
根据题目可知有钩子
主函数
int __fastcall main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
__int64 argv_1; // rdx
__int64 envp_1; // r8
char *Str1; // [rsp+20h] [rbp-98h]
char input[112]; // [rsp+30h] [rbp-88h] BYREF
sub_140001970("Give your bait:", argv, envp);
memset(input, 0, 0x64uLL);
sub_1400019F0("%s", input);
v3 = strlen(input);
Str1 = (char *)sub_1400014B0(input, v3);
if ( !strcmp(Str1, "tAZ5tAZ5tAZ5vg7F2RZF2RZQ0gv5yCfAxSZKzq==") )
sub_140001970("The fisherman like your bait.\n", argv_1, envp_1);
else
sub_140001970("The fisherman doesn't like your bait.\n", argv_1, envp_1);
free(Str1);
system("pause");
return 0;
}
查找字符串有个strcmp

交叉引用
char sub_140001020()
{
HMODULE hModule; // [rsp+20h] [rbp-18h]
hModule = GetModuleHandleA("ucrtbase.dll");
strcmp_0 = (int (__cdecl *)(const char *, const char *))GetProcAddress(hModule, "strcmp");
sub_140001070(strcmp_0, (__int64)a2);
return 1;
}
勾取了strcmp,跟进a2
__int64 __fastcall a2(_BYTE *i_1)
{
char v2; // [rsp+20h] [rbp-C8h]
int k; // [rsp+24h] [rbp-C4h]
int j; // [rsp+28h] [rbp-C0h]
_BYTE v5[64]; // [rsp+30h] [rbp-B8h]
int n64; // [rsp+70h] [rbp-78h]
_BYTE *i; // [rsp+78h] [rbp-70h]
_BYTE v9[16]; // [rsp+80h] [rbp-68h] BYREF
_BYTE buf[64]; // [rsp+90h] [rbp-58h] BYREF
sub_140001430();
memset(buf, 0, sizeof(buf));
n64 = 0;
for ( i = i_1; *i; ++i )
++n64;
if ( n64 != 64 )
return 0xFFFFFFFFLL;
memcpy(buf, i_1, sizeof(buf));
v9[0] = 17;
v9[1] = 34;
v9[2] = 51;
v9[3] = 68;
v9[4] = 85;
v9[5] = 102;
v9[6] = 119;
v9[7] = -120;
for ( j = 0; j < 8; ++j )
teaenc(&buf[8 * j], v9);
v5[0] = 8;
v5[1] = -18;
v5[2] = 89;
v5[3] = 77;
v5[4] = 13;
v5[5] = -32;
v5[6] = -64;
v5[7] = -119;
v5[8] = -95;
v5[9] = -104;
v5[10] = -78;
v5[11] = -69;
v5[12] = -49;
v5[13] = 112;
v5[14] = 127;
v5[15] = -27;
v5[16] = -24;
v5[17] = 47;
v5[18] = -102;
v5[19] = -118;
v5[20] = 32;
v5[21] = -53;
v5[22] = 116;
v5[23] = 18;
v5[24] = -14;
v5[25] = 48;
v5[26] = 120;
v5[27] = 31;
v5[28] = 14;
v5[29] = -21;
v5[30] = 31;
v5[31] = -120;
v5[32] = -56;
v5[33] = -68;
v5[34] = 78;
v5[35] = -8;
v5[36] = 82;
v5[37] = 19;
v5[38] = 83;
v5[39] = -117;
v5[40] = -99;
v5[41] = -65;
v5[42] = 102;
v5[43] = 11;
v5[44] = 106;
v5[45] = -84;
v5[46] = 33;
v5[47] = 79;
v5[48] = -23;
v5[49] = 31;
v5[50] = 70;
v5[51] = 70;
v5[52] = -98;
v5[53] = -53;
v5[54] = -6;
v5[55] = 99;
v5[56] = -93;
v5[57] = -123;
v5[58] = 20;
v5[59] = -55;
v5[60] = 46;
v5[61] = -9;
v5[62] = 16;
v5[63] = -59;
v2 = 1;
for ( k = 0; k < 64; ++k )
{
if ( buf[k] != v5[k] )
{
v2 = 0;
break;
}
}
if ( v2 )
return 0;
else
return (unsigned int)-1;
}
是个tea加密
写出解密脚本
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#define DELTA 0x6D6DD6D7u
void tea_decrypt_block(uint8_t *c8, uint8_t *out8, uint32_t a2[4]) {
// load little-endian u32 words
uint32_t v3 = (uint32_t)c8[0] | ((uint32_t)c8[1] << 8) | ((uint32_t)c8[2] << 16) | ((uint32_t)c8[3] << 24);
uint32_t v4 = (uint32_t)c8[4] | ((uint32_t)c8[5] << 8) | ((uint32_t)c8[6] << 16) | ((uint32_t)c8[7] << 24);
uint32_t sum = (uint32_t)(0u - (32u * DELTA));
for (int i = 0; i < 32; ++i) {
uint32_t tmp_v4 = ( (a2[3] + (v3 >> 5))
^ ( (sum + v3) )
^ ( (a2[2] + (v3 << 4)) ) );
v4 -= tmp_v4;
uint32_t tmp_v3 = ( (a2[1] + (v4 >> 5))
^ ( (sum + v4) )
^ ( (a2[0] + (v4 << 4)) ) );
v3 -= tmp_v3;
sum += DELTA;
}
out8[0] = (uint8_t)(v3 & 0xFF);
out8[1] = (uint8_t)((v3 >> 8) & 0xFF);
out8[2] = (uint8_t)((v3 >> 16) & 0xFF);
out8[3] = (uint8_t)((v3 >> 24) & 0xFF);
out8[4] = (uint8_t)(v4 & 0xFF);
out8[5] = (uint8_t)((v4 >> 8) & 0xFF);
out8[6] = (uint8_t)((v4 >> 16) & 0xFF);
out8[7] = (uint8_t)((v4 >> 24) & 0xFF);
}
int main(void) {
int8_t v5_signed[64] = {
8, -18, 89, 77, 13, -32, -64, -119,
-95, -104, -78, -69, -49, 112, 127, -27,
-24, 47, -102, -118, 32, -53, 116, 18,
-14, 48, 120, 31, 14, -21, 31, -120,
-56, -68, 78, -8, 82, 19, 83, -117,
-99, -65, 102, 11, 106, -84, 33, 79,
-23, 31, 70, 70, -98, -53, -6, 99,
-93, -123, 20, -55, 46, -9, 16, -59
};
uint8_t ctext[64];
for (int i = 0; i < 64; ++i) {
ctext[i] = (uint8_t)v5_signed[i];
}
uint8_t v9_bytes[16] = { 17,34,51,68, 85,102,119,(uint8_t) (-120), 0,0,0,0, 0,0,0,0 };
uint32_t a2[4];
memcpy(a2, v9_bytes, 16);
uint8_t plain[64];
for (int b = 0; b < 8; ++b) {
tea_decrypt_block(ctext + b*8, plain + b*8, a2);
}
printf("Decrypted (ASCII):\n");
char outstr[65];
memcpy(outstr, plain, 64);
outstr[64] = '\0';
printf("%s\n", outstr);
printf("\nDecrypted (hex):\n");
for (int i = 0; i < 64; ++i) {
printf("%02x", plain[i]);
}
printf("\n");
return 0;
}
再base64

flag{Fisherman_is_very_satisfied_with_your_bait}
re3 trap
ida打开,给main函数美化一下

在左边的函数框中发现这个函数
int64 __fastcall sub_7FF6E9D01200(__int64 a1)
{
int i; // [rsp+20h] [rbp-38h]
int j; // [rsp+24h] [rbp-34h]
_BYTE _1i4W[16]; // [rsp+28h] [rbp-30h] BYREF
qmemcpy(_1i4W, "1i4W", 4);
_1i4W[4] = -103;
_1i4W[5] = 53;
_1i4W[6] = 119;
_1i4W[7] = 17;
qmemcpy(&_1i4W[8], "6Rv", 3);
if ( IsDebuggerPresent() )
{
for ( i = 0; i < 32; ++i )
Buf2[i] ^= i;
for ( j = 0; j < 11; ++j )
_1i4W[j] ^= (_BYTE)j + 1;
}
qmemcpy(1i4W, _1i4W, 0xBuLL);
return a1;
}
调试就改变数据
查看pdata段,这个函数在main函数之前就初始化了

汇编这里jz改成jnz

再调试,异或表和密文就没有改过
写出脚本:
table = [0x31, 0x69, 0x34, 0x57, 0x99, 0x35, 0x77, 0x11, 0x36, 0x52, 0x76]
buf2 = [
0x57,0x51,0x04,0x3B,0xD9,0xB6,0xF1,0x96,0xFF,0xC4,0xF2,0x96,0xCC,0xA6,0xB4,0x1B,
0x4D,0x01,0x60,0x32,0x04,0x2C,0x5B,0x43,0x47,0x72,0xB4,0xB5,0xB0,0x96,0xD0,0xFE
]
length = 0x20
E = buf2[:length]
orig = [0] * length
for i in range(length):
b = E[i]
if i > 0:
b ^= E[i-1]
if (i % 2) == 1:
b ^= (table[i % 11] + 1) & 0xFF
else:
b ^= table[i % 11]
orig[i] = b & 0xFF
orig_bytes = bytes(orig)
print(orig_bytes)
flag{Y0u_h@V3_E5c4ped_Fr0m_7r4p}
PS:之前有些反调试好像被我nop掉了
re4 babyre
本来是一个去混淆的题,不知道为什么ida9自动去了混淆。。
// The function seems has been flattened
__int64 __fastcall main(int a1, char **a2, char **a3)
{
char input[112]; // [rsp+10h] [rbp-E0h] BYREF
char dest[108]; // [rsp+80h] [rbp-70h] BYREF
int v6; // [rsp+ECh] [rbp-4h]
v6 = 0;
memcpy(dest, &src_, 0x64uLL);
memset(input, 0, 0x64uLL);
__isoc99_scanf(&unk_4020E4, input);
enc(input);
if ( !strcmp(input, dest) )
printf("Success!\n");
else
printf("Fail!\n");
return 0LL;
}
// The function seems has been flattened
__int64 __fastcall enc(char *s)
{
size_t i_2; // rsi
size_t i_4; // rsi
__int64 result; // rax
_QWORD v4[2]; // [rsp+0h] [rbp-60h] BYREF
int v5; // [rsp+14h] [rbp-4Ch]
int v6; // [rsp+18h] [rbp-48h]
int i; // [rsp+1Ch] [rbp-44h]
char *sa; // [rsp+20h] [rbp-40h]
_DWORD *v9; // [rsp+28h] [rbp-38h]
_DWORD *v10; // [rsp+30h] [rbp-30h]
size_t i_1; // [rsp+38h] [rbp-28h]
__int64 v12; // [rsp+40h] [rbp-20h]
int v13; // [rsp+4Ch] [rbp-14h]
size_t i_3; // [rsp+50h] [rbp-10h]
int v15; // [rsp+58h] [rbp-8h]
int v16; // [rsp+5Ch] [rbp-4h]
v4[1] = s;
v9 = &v4[-2];
v10 = &v4[-2];
sa = s;
sub_401180();
v5 = 0;
v6 = 0;
for ( i = 0; ; ++i )
{
i_1 = i;
i_2 = strlen(sa);
if ( i_1 >= i_2 )
break;
v6 = (v6 + 1) % 256;
v5 = ((unsigned __int8)byte_404070[v6] + v5) % 256;
*v10 = (unsigned __int8)byte_404070[v6];
v12 = v5;
byte_404070[v6] = byte_404070[v5];
byte_404070[v5] = *v10;
*v9 = (unsigned __int8)byte_404070[((unsigned __int8)byte_404070[v5] + (unsigned __int8)byte_404070[v6]) % 256];
sa[i] ^= *v9;
v13 = i + 1;
}
for ( i = 0; ; ++i )
{
i_3 = i;
i_4 = strlen(sa);
LODWORD(result) = 746392057;
if ( i_3 >= i_4 )
break;
v15 = (unsigned __int8)(8 * sa[i]);
sa[i] = ((int)(unsigned __int8)sa[i] >> 5) | v15;
v16 = i + 1;
}
return result;
}
// The function seems has been flattened
__int64 sub_401180()
{
__int64 result; // rax
size_t v1; // rsi
size_t v2; // [rsp+0h] [rbp-50h] BYREF
unsigned int v3; // [rsp+14h] [rbp-3Ch]
int v4; // [rsp+18h] [rbp-38h]
unsigned int i; // [rsp+1Ch] [rbp-34h]
size_t *v6; // [rsp+20h] [rbp-30h]
void *dest; // [rsp+28h] [rbp-28h]
unsigned int i_1; // [rsp+30h] [rbp-20h]
char i_2; // [rsp+37h] [rbp-19h]
unsigned int i_3; // [rsp+38h] [rbp-18h]
unsigned int v11; // [rsp+3Ch] [rbp-14h]
unsigned int i_4; // [rsp+40h] [rbp-10h]
int v13; // [rsp+44h] [rbp-Ch]
char v14; // [rsp+4Bh] [rbp-5h]
unsigned int v15; // [rsp+4Ch] [rbp-4h]
v6 = &v2 - 2;
dest = &v2 - 14;
memcpy(&v2 - 14, &src__0, 0x64uLL);
for ( i = 0; ; ++i )
{
i_1 = i;
if ( i >= 256 )
break;
i_2 = i;
i_3 = i;
byte_404070[i] = i;
v11 = i + 1;
}
v3 = 0;
v4 = 0;
for ( i = 0; ; ++i )
{
i_4 = i;
LODWORD(result) = 0x6C3830AE;
if ( i >= 256 )
break;
*(_DWORD *)v6 = (unsigned __int8)byte_404070[i];
v13 = *(_DWORD *)v6 + v4;
v14 = *((_BYTE *)dest + v3);
v4 = (unsigned __int8)(v14 + v13);
byte_404070[i] = byte_404070[(unsigned __int8)(v14 + v13)];
byte_404070[v4] = *(_DWORD *)v6;
v2 = ++v3;
v1 = strlen((const char *)dest);
if ( v2 >= v1 )
v3 = 0;
v15 = i + 1;
}
return result;
}
一个rc4再循环左移3
写出脚本
src0 = [0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]
dest = [0xC6, 0xAC, 0xEE, 0x8B, 0x57, 0x04, 0x64, 0x3A,
0xA7, 0x3B, 0x84, 0x67, 0xAC, 0xD7, 0x8E, 0xD8,
0x1D, 0x03, 0x85, 0x55, 0xF6, 0x51, 0x90]
def rc4_init(key):
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + key[i % len(key)]) & 0xFF
S[i], S[j] = S[j], S[i]
return S
def rc4_crypt(data, S):
i = j = 0
out = []
for byte in data:
i = (i + 1) & 0xFF
j = (j + S[i]) & 0xFF
S[i], S[j] = S[j], S[i]
K = S[(S[i] + S[j]) & 0xFF]
out.append(byte ^ K)
return out
def ror3(x):
return ((x >> 3) | ((x << 5) & 0xFF)) & 0xFF
rot_reversed = [ror3(x) for x in dest]
S = rc4_init(src0)
plain_bytes = rc4_crypt(rot_reversed, S)
flag = bytes(plain_bytes).decode()
print(flag)
re5 ezmath
用Z3求解
import z3
s = z3.Solver()
flag = [z3.BitVec('%d' % i,8) for i in range(80)]
v = {}
for n in range(4,83):
v[n] = flag[83 - n]
s0 = flag[0]
s.add(93 * v[55] == 131)
s.add(-92 * v[55] + 91 * v[20] == 98)
s.add(79 * v[48] - 117 * v[55] - 55 * v[20] == 88)
s.add(121 * v[59] + 58 * v[55] -124 * v[20] + 104 * v[48] == 221)
s.add(2 * v[59] - 85 * v[55] + 44 * v[20] - 100 * v[48] - 47 * v[4] == 156)
s.add(-67 * v[48] - 110 * v[55] -10 * v[59] + 57 * v[58] + 11 * v[4] + 27 * v[20] == 146)
s.add(110 * v[55] + 53 * v[58] + 47 * v[62] - 22 * v[59] -72 * v[20] - 18 * v[48] - 110 * v[4] == 249)
s.add(120 * v[55] + 115 * v[58] + 34 * v[62] + 90 * v[59] + 86 * v[20] + 126 * v[48] -63 * v[4] - 75 * v[15] == 19)
s.add(46 * v[55] - 84 * v[58] -18 * v[59] - 96 * v[62] + 17 * v[29] -119 * v[48] -9 * v[15] + 81 * v[20] + 18 * v[4] == 225)
s.add(-86 * v[62] + 104 * v[59] + 26 * v[55] + 124 * v[58] -117 * v[20] + 48 * v[29] + 107 * v[6] - 83 * v[15] - 101 * v[4] == 64)
s.add(28 * v[6] + 100 * v[15] + 90 * v[20] + 117 * v[29] + 79 * v[77] - 30 * v[62] -41 * v[55] - 14 * v[58] - 24 * v[4] == 206)
s.add(40 * v[48] + 59 * v[51] + 50 * v[58] + 123 * v[59] -115 * v[62] + 80 * v[77] + 74 * v[20] - 80 * v[29] - 103 * v[4] == 50)
s.add(36 * v[58] + 89 * v[59] + 31 * v[62] + 85 * v[73] -77 * v[51] + 95 * v[55] + 8 * v[20] + 39 * v[48] + 9 * v[6] == 167)
s.add(-33 * v[48] + 92 * v[55] + 6 * v[59] - 59 * v[62] + 68 * v[77] + 57 * v[69] + 7 * v[15] + 20 * v[20] - 100 * v[4] == 121)
s.add(122 * v[77] - 46 * v[59] -54 * v[51] + 40 * v[58] -45 * v[38] + 91 * v[48] + 30 * v[6] + 96 * v[20] - 105 * v[4] == 200)
s.add(-106 * v[55] - 111 * v[58] + 72 * v[59] + 28 * v[73] -53 * v[77] + 39 * v[75] + 58 * v[38] + 90 * v[51] + 68 * v[6] == 98)
s.add(-65 * v[6] + 66 * v[29] -91 * v[38] + 51 * v[41] -14 * v[51] - 72 * v[55] -68 * v[69] + 103 * v[59] + 11 * v[4] == 90)
s.add(-117 * v[29] + 56 * v[38] + 10 * v[41] + 81 * v[48] + 41 * v[51] - 13 * v[53] -27 * v[77] - 97 * v[62] - 48 * v[6] == 51)
s.add(-120 * v[38] - 39 * v[41] + 120 * v[53] - 99 * v[59] + 127 * v[62] - 16 * v[73] -71 * v[20] - 97 * v[37] + 42 * v[6] == 136)
s.add(111 * v[31] - 18 * v[37] -115 * v[73] + 30 * v[55] -39 * v[48] + 25 * v[53] -123 * v[15] + 92 * v[20] - 72 * v[6] == 45)
s.add(34 * v[77] + 90 * v[75] + 113 * v[54] + 14 * v[59] -68 * v[48] + 19 * v[51] + 78 * v[38] - 25 * v[41] - 59 * v[15] == 150)
s.add(-60 * v[37] + 38 * v[38] + 79 * v[47] -121 * v[51] + 119 * v[73] - 53 * v[53] + 93 * v[20] - 69 * v[29] - 95 * v[4] == 117)
s.add(97 * v[41] + 76 * v[48] + 27 * v[54] + 23 * v[55] + 45 * v[77] - 76 * v[59] -107 * v[29] + 124 * v[31] + 47 * v[5] == 155)
s.add(-119 * v[37] - 22 * v[38] + 43 * v[47] + 124 * v[58] -45 * v[77] + 38 * v[59] + 127 * v[31] -119 * v[35] + 46 * v[15] == 117)
s.add(-2 * v[35] + 10 * v[37] -75 * v[41] + 4 * v[51] + 77 * v[62] - 72 * v[55] + 69 * v[22] + 82 * v[31] + 112 * v[20] == 16)
s.add(-65 * v[81] - 58 * v[59] + 22 * v[37] - 58 * v[54] + 69 * v[22] + 33 * v[35] -124 * v[6] + 60 * v[20] + 74 * v[4] == 23)
s.add(-72 * v[20] + 71 * v[22] -80 * v[29] - 98 * v[31] + 7 * v[34] + 65 * v[38] -93 * v[69] + 16 * v[62] + 7 * v[6] == 124)
s.add(-38 * v[29] + 117 * v[31] + 67 * v[59] + 5 * v[58] -59 * v[38] - 14 * v[41] + 34 * v[6] - 11 * v[12] + 34 * v[5] == 210)
s.add(15 * v[31] + 84 * v[34] -127 * v[58] - 5 * v[37] -94 * v[81] - 91 * v[59] -104 * v[12] + 61 * v[23] - 73 * v[4] == 217)
s.add(-73 * v[34] - 117 * v[35] -68 * v[38] + 119 * v[69] + 17 * v[74] -119 * v[81] + 31 * v[23] + 30 * v[31] -123 * v[5] == 59)
s.add(61 * v[72] - 60 * v[74] -2 * v[41] - 17 * v[55] + 89 * v[35] + 9 * v[37] -29 * v[6] - 67 * v[31] + 44 * v[5] == 134)
s.add(-102 * v[77] + 43 * v[81] + 2 * v[59] - 93 * v[62] + 25 * v[41] + 40 * v[48] + 29 * v[23] + 41 * v[35] + 95 * v[16] == 139)
s.add(-36 * v[16] + 123 * v[23] -107 * v[77] - 63 * v[57] + 94 * v[47] - 69 * v[52] + 97 * v[29] - 30 * v[34] -82 * v[4] + 29 * v[12] == 139)
s.add(-62 * v[29] - 89 * v[31] + 68 * v[38] - 95 * v[62] + 110 * v[81] - 65 * v[77] + 73 * v[18] - 22 * v[23] - 59 * v[4] == 30)
s.add(-20 * v[12] + 60 * v[37] + 104 * v[81] + 43 * v[74] -8 * v[69] - 5 * v[73] + 32 * v[59] - 47 * v[60] + 12 * v[4] == 63)
s.add(-25 * v[19] - 114 * v[35] + 104 * v[69] - 22 * v[60] -61 * v[51] - 59 * v[58] -7 * v[47] - 58 * v[49] -97 * v[5] - 65 * v[6] == 230)
s.add(-39 * v[31] + 111 * v[32] -30 * v[48] - 92 * v[54] + 5 * v[55] - 28 * v[57] -6 * v[18] + 22 * v[19] + 61 * v[4] == 224)
s.add(89 * v[20] - 107 * v[37] -120 * v[41] + 29 * v[48] + 117 * v[64] + 110 * v[59] -77 * v[53] + 12 * v[55] + 80 * v[12] == 6)
s.add(76 * v[41] + 71 * v[58] + 19 * v[61] - 45 * v[69] -61 * v[73] + 36 * v[74] -74 * v[20] + 45 * v[34] - 20 * v[16] == 81)
s.add(-48 * v[19] + 17 * v[32] + 115 * v[38] - 18 * v[53] -14 * v[62] + 43 * v[79] -25 * v[5] - 58 * v[15] + 117 * v[4] == 76)
s.add(58 * v[22] - 82 * v[29] -77 * v[31] + 69 * v[44] -64 * v[51] - 75 * v[55] -12 * v[60] + 47 * v[66] + 95 * v[4] + 62 * v[19] == 78)
s.add(38 * v[58] - 44 * v[61] + 109 * s0 -107 * v[75] + 20 * v[29] - 74 * v[53] -39 * v[6] + 80 * v[18] + 101 * v[4] == 115)
s.add(-122 * v[18] - 49 * v[29] + 3 * v[51] + 34 * v[57] -17 * v[66] + 109 * v[61] + 91 * v[7] - 10 * v[16] + 76 * v[5] == 19)
s.add(72 * v[32] + 57 * v[35] + 19 * v[42] - 92 * v[57] + 17 * v[58] + 16 * v[62] + 68 * v[73] + 84 * v[64] + 127 * v[15] == 27)
s.add(-15 * v[47] + 80 * v[53] -73 * v[81] + 72 * v[77] + 16 * v[55] + 38 * v[57] -33 * v[32] -121 * v[40] + 123 * v[22] == 29)
s.add(-5 * v[68] - 8 * v[79] + 74 * v[58] + 70 * v[66] + 88 * v[32] + 40 * v[53] + 17 * v[7] + 90 * v[29] -102 * v[5] == 172)
s.add(-8 * v[29] + 122 * v[58] + 91 * v[60] + 71 * v[62] + 10 * v[66] -118 * v[72] -114 * v[20] - 72 * v[22] - 25 * v[8] == 158)
s.add(-68 * v[73] - 33 * v[72] -27 * v[63] + 104 * v[69] -114 * v[40] + 41 * v[62] -114 * v[8] + 28 * v[29] - 78 * v[7] == 94)
s.add(67 * v[20] - 106 * v[42] -36 * v[53] + 71 * v[64] + 109 * v[78] - 98 * v[66] -29 * v[6] - 88 * v[7] -117 * v[4] == 176)
s.add(-23 * v[81] - 57 * v[80] + 77 * v[68] - 68 * v[75] -94 * v[64] + 15 * v[66] + 66 * v[35] - 80 * v[42] + 59 * v[19] == 254)
s.add(97 * v[76] - 126 * v[66] -90 * v[54] - 60 * v[63] + 34 * v[48] + 45 * v[51] + 53 * v[18] + 7 * v[37] -105 * v[15] == 46)
s.add(-59 * v[20] + 66 * v[33] -47 * v[61] + 2 * v[62] + 44 * v[74] + 51 * v[79] + 83 * v[82] + 98 * v[80] + 20 * v[8] -81 * v[19] == 45)
s.add(29 * v[38] - 107 * v[46] -105 * v[58] - 90 * v[66] -58 * v[76] - 41 * v[72] -67 * v[5] + 98 * v[6] -125 * v[4] == 199)
s.add(-102 * v[41] - 73 * v[45] -10 * v[76] - 75 * v[64] + 127 * v[59] + 1 * v[46] -123 * v[32] - 92 * v[40] -102 * v[12] == 164)
s.add(82 * v[12] - 27 * v[28] + 111 * v[73] + 97 * v[62] -1 * v[80] + 79 * v[29] + 22 * v[41] + 86 * v[4] - 87 * v[5] == 248)
s.add(-21 * v[80] - 102 * v[79] -107 * v[68] + 58 * v[72] -93 * v[56] - 14 * v[57] + 37 * v[23] + 68 * v[40] + 84 * v[16] == 116)
s.add(62 * v[29] - 20 * v[35] + 107 * v[41] + 30 * v[60] -37 * v[80] - 2 * v[76] + 40 * v[20] + 13 * v[28] -107 * v[14] == 118)
s.add(113 * v[55] + 107 * v[70] -13 * v[72] - 28 * v[78] + 41 * v[38] + 122 * v[53] -95 * v[27] + 40 * v[31] -99 * v[4] - 79 * v[6] == 119)
s.add(-85 * v[31] + 21 * v[44] + 50 * v[70] + 55 * v[61] -115 * v[51] - 40 * v[59] + 110 * v[6] + 11 * v[16] + 15 * v[5] == 0)
s.add(39 * v[71] - 95 * v[68] + 48 * v[57] + 105 * v[62] + 32 * v[48] - 78 * v[51] + 56 * v[37] - 89 * v[41] + 99 * v[34] == 164)
s.add(17 * v[48] - 94 * v[51] -12 * v[54] - 19 * v[59] -28 * v[62] + 17 * v[65] + 45 * v[81] - 27 * v[66] -126 * v[24] - 45 * v[35] == 214)
s.add(-121 * v[41] + 120 * v[64] + 72 * v[76] -116 * v[79] + 110 * v[32] + 55 * v[38] -41 * v[19] - 4 * v[23] + 59 * v[9] == 231)
s.add(-73 * v[76] - 118 * v[69] + 69 * v[55] + 14 * v[68] -3 * v[36] - 111 * v[40] + 125 * v[14] - 72 * v[16] - 18 * v[4] == 138)
s.add(-80 * v[58] + 97 * v[61] -92 * v[68] - 99 * v[69] + 108 * v[82] - 20 * v[75] -73 * v[46] + 90 * v[51] - 69 * v[11] == 85)
s.add(71 * v[50] + 88 * v[53] -97 * v[78] + 34 * v[80] -31 * v[56] - 53 * v[60] -76 * v[14] - 47 * v[42] - 89 * v[5] == 72)
s.add(-57 * v[55] + 114 * v[62] -69 * v[65] + 59 * v[79] -100 * s0 + 118 * v[81] -14 * v[18] + 111 * v[25] + 60 * v[16] == 66)
s.add(51 * v[43] - 15 * v[45] + 9 * v[46] - 85 * v[47] -53 * v[74] + 75 * v[61] -62 * v[35] - 37 * v[40] + 4 * v[15] == 250)
s.add(23 * v[29] + 59 * v[30] -109 * v[37] + 90 * v[54] -66 * v[58] - 86 * v[68] + 27 * v[81] -65 * s0 -69 * v[5] + 91 * v[17] == 126)
s.add(94 * v[48] - 7 * v[56] -49 * v[72] - 65 * v[73] + 27 * v[76] + 74 * v[82] -48 * v[23] - 87 * v[35] - 39 * v[21] == 250)
s.add(19 * v[33] + 122 * v[51] + 66 * v[60] + 64 * v[74] -85 * v[80] - 89 * v[78] + 95 * v[19] + 42 * v[22] -127 * v[16] == 147)
s.add(3 * v[54] - 93 * v[66] -93 * v[67] + 29 * v[68] + 50 * v[82] -123 * v[78] -80 * v[23] -114 * v[47] - 71 * v[6] == 243)
s.add(117 * v[82] + 15 * v[64] -97 * v[53] + 25 * v[55] -51 * v[28] + 29 * v[31] -86 * v[15] + 25 * v[25] + 109 * v[10] == 109)
s.add(-81 * v[37] - 99 * v[38] -87 * v[79] + 13 * v[75] + 69 * v[47] + 13 * v[62] -70 * v[7] - 81 * v[13] -123 * v[4] == 136)
s.add(-61 * v[29] - 33 * v[30] -69 * v[49] - 66 * v[55] + 40 * v[56] - 56 * v[71] + 52 * v[80] - 65 * v[78] -75 * v[11] + 16 * v[25] == 125)
s.add(-42 * v[10] + 59 * v[13] -20 * v[22] - 71 * v[39] -89 * v[46] + 121 * v[50] -38 * v[67] + 71 * v[79] + 1 * v[60] - 24 * v[6] == 97)
s.add(55 * v[26] - 49 * v[29] -99 * v[38] + 102 * v[68] -112 * v[69] + 86 * v[76] -61 * v[14] + 58 * v[21] - 41 * v[7] == 206)
s.add(44 * v[35] - 74 * v[37] -84 * v[42] -119 * v[54] + 96 * v[78] + 24 * v[80] + 90 * v[26] - 89 * v[27] -109 * v[6] == 69)
s.add(49 * v[24] + 85 * v[29] -78 * v[34] + 123 * v[38] -127 * v[58] - 9 * v[54] + 125 * v[70] + 128 * s0 + 81 * v[4] == 253)
s.add(-64 * v[39] - 57 * v[43] + 39 * s0 - 18 * v[65] + 40 * v[36] -124 * v[37] + 9 * v[30] - 5 * v[17] + 74 * v[12] == 168)
s.add(8 * v[18] + 109 * v[28] + 79 * v[54] - 26 * v[68] -92 * v[75] + 26 * v[72] + 108 * v[30] + 117 * v[52] + 101 * v[9] == 132)
if s.check() == z3.sat:
m = s.model()
f = ''.join(chr(m[flag[i]].as_long()) for i in range(80))
print(f)
else:
print('unsat')
flag{we1COME_7#_THe_zE_Wor1d_HOpe_You_3NjOY_it_bjjf2xmDY2hEWJDarycY4RMpKlB?dSkt}
re6 strangeEnc
ida打开,8字节一块的加密,而且用#填充
int __fastcall main(int argc, const char **argv, const char **envp)
{
size_t v3; // rax
size_t v4; // rax
char *input; // rbx
char *input_2; // rbp
unsigned __int64 *input_1; // rcx
__int64 i; // rax
_main(argc, argv, envp);
printf("input your flag:\n");
scanf("%s", input);
v3 = strlen(input);
if ( (v3 & 7) != 0 )
{
strncat(input, "#######", 8 - (v3 & 7));
v3 = strlen(input);
}
v4 = v3 >> 3;
if ( (_DWORD)v4 )
{
input = input;
input_2 = &input[8 * (unsigned int)(v4 - 1) + 8];
do
{
input_1 = (unsigned __int64 *)input;
input += 8;
sub_7FF6B20E1CC0(input_1, "Koishi__");
}
while ( input != input_2 );
}
for ( i = 0LL; i != 40; ++i )
{
if ( input[i] != ans[i] )
{
printf("wrong \n");
return 0;
}
}
printf("right \n");
return 0;
}
跟进加密函数sub_7FF6B20E1CC0
unsigned __int64 *__fastcall sub_7FF6B20E1CC0(unsigned __int64 *input, _QWORD *Koishi__)
{
__int64 v2; // rsi
__int64 v3; // rax
unsigned __int64 v4; // rbx
__int64 *v5; // rdx
char v6; // cl
__int64 v7; // rax
int *v8; // rdi
__int64 v9; // r10
unsigned __int64 v10; // r8
__int64 *v11; // rdx
char v12; // cl
unsigned int v13; // eax
unsigned int v14; // eax
unsigned int v15; // r8d
unsigned __int64 v16; // r10
__int64 *v17; // rdx
char v18; // cl
__int64 v19; // rax
int v20; // eax
__int64 v21; // r8
__int64 *v22; // r11
unsigned __int64 v23; // rsi
unsigned __int64 v24; // r8
char v25; // cl
__int64 v26; // rax
unsigned __int64 *input_1; // rax
int v28; // [rsp+2Ch] [rbp-8Ch]
__int64 v29; // [rsp+30h] [rbp-88h] BYREF
__int64 v30; // [rsp+38h] [rbp-80h]
__int64 v31; // [rsp+40h] [rbp-78h]
__int64 v32; // [rsp+48h] [rbp-70h]
__int64 v33; // [rsp+50h] [rbp-68h] BYREF
__int64 v34; // [rsp+58h] [rbp-60h]
__int64 v35; // [rsp+60h] [rbp-58h] BYREF
__int64 v36; // [rsp+68h] [rbp-50h]
_BYTE v37[72]; // [rsp+70h] [rbp-48h] BYREF
v2 = 0LL;
v3 = sub_7FF6B20E1360(*Koishi__);
sub_7FF6B20E1550(v3);
v4 = *input;
v30 = 0x40C141C242C343CLL;
v29 = 0x20A121A222A323ALL;
v31 = 0x60E161E262E363ELL;
v33 = 0x109111921293139LL;
v32 = 0x810182028303840LL;
v35 = 0x50D151D252D353DLL;
v34 = 0x30B131B232B333BLL;
v36 = 0x70F171F272F373FLL;
v5 = &v29;
do
{
v6 = (unsigned __int8)&v29 + 63 - (_BYTE)v5;
v7 = (v4 >> (64 - *(_BYTE *)v5)) & 1;
v5 = (__int64 *)((char *)v5 + 1);
v2 |= v7 << v6;
}
while ( v37 != (_BYTE *)v5 );
v8 = (int *)&Keys;
v28 = HIDWORD(v2);
while ( 1 )
{
v9 = *(_QWORD *)v8;
v10 = 0LL;
v29 = 0x504050403020120LL;
v31 = 0x11100F0E0D0C0D0CLL;
v30 = 0xB0A090809080706LL;
v33 = 0x1B1A191819181716LL;
v32 = 0x1514151413121110LL;
v34 = 0x1201F1E1D1C1D1CLL;
v11 = &v29;
do
{
v12 = (unsigned __int8)&v29 + 47 - (_BYTE)v11;
v13 = ((unsigned int)v2 >> (32 - *(_BYTE *)v11)) & 1;
v11 = (__int64 *)((char *)v11 + 1);
v10 |= v13 << v12;
}
while ( &v35 != v11 );
v14 = sub_7FF6B20E19B0(v10 ^ v9);
v15 = 0;
v16 = v14;
v30 = 0xA1F12051A170F01LL;
v29 = 0x111C0C1D15140710LL;
v31 = 0x9031B200E180802LL;
v32 = 0x19040B16061E0D13LL;
v17 = &v29;
do
{
v18 = (unsigned __int8)&v29 + 31 - (_BYTE)v17;
v19 = (v16 >> (32 - *(_BYTE *)v17)) & 1;
v17 = (__int64 *)((char *)v17 + 1);
v15 |= v19 << v18;
}
while ( &v33 != v17 );
v20 = v28;
v8 += 2;
v28 = v2;
v21 = v20 ^ v15;
if ( &initialized == v8 )
break;
LODWORD(v2) = v21;
}
v22 = &v29;
v23 = (v21 << 32) | (unsigned int)v2;
v24 = 0LL;
v29 = 0x2040183810300828LL;
v30 = 0x1F3F17370F2F0727LL;
v31 = 0x1E3E16360E2E0626LL;
v32 = 0x1D3D15350D2D0525LL;
v33 = 0x1C3C14340C2C0424LL;
v34 = 0x1B3B13330B2B0323LL;
v35 = 0x1A3A12320A2A0222LL;
v36 = 0x1939113109290121LL;
do
{
v25 = (unsigned __int8)&v29 + 63 - (_BYTE)v22;
v26 = (v23 >> (64 - *(_BYTE *)v22)) & 1;
v22 = (__int64 *)((char *)v22 + 1);
v24 |= v26 << v25;
}
while ( v37 != (_BYTE *)v22 );
input_1 = input;
*input = v24;
return input_1;
}
des的盒一个个对照过来,是魔改的一个des加密,而且伪代码里很贴心地标明了key,这就好办了
根据 DES Feistel 结构的对称性,L xor F(R,key)后R和L互换,key在加密时用的是1-16,还原时依旧是用 F(R,key) 来xor L还原出L再互换,所以用key从16-1就行
input patch成密文,每轮换下key,得到flag

flag{Fun_Fact_its_littleEndian_DES}
re7 wtf
进去一个输入flag的网站

f12开发者工具

搜下源码就可以搜到两个js文件
看html的话两个js文件放在这里

看一下src.js
var _a;
var ___Key = 'Komeji Satori';
var ans = [
94, 49, 141, 165, 142, 18, 244, 41, 100, 131, 44, 13, 99, 120, 148, 85, 226, 180, 172, 152, 204, 85, 244, 48
];
(_a = document.querySelector('#submit')) === null || _a === void 0 ? void 0 : _a.addEventListener('click', function () {
var flag = document.querySelector('#input');
var input = flag.value;
var bytes = new TextEncoder().encode(input);
bytes[0] ^= 0x12;
bytes[1] ^= 0x34;
bytes[2] ^= 0x56;
bytes[3] ^= 0x78;
console.log(___Key);
bytes = encode(bytes, ___Key);
for (var i = 0; i < bytes.length; i++) {
bytes[i] ^= ___Key[i % ___Key.length].charCodeAt(0);
}
for (var i = 0; i < ans.length; i++) {
if (bytes[i] !== ans[i]) {
document.querySelector('#input').value = 'Wrong flag!';
return;
}
}
document.querySelector('#input').value = 'Correct flag! you find Koishi!';
document.body.style.backgroundImage = 'url(\'koishi.webp\')';
document.body.style.backgroundPosition = 'center';
});
function encode(input, key) {
var _a;
var keyBytes = new Uint8Array(16);
var keyData = new TextEncoder().encode(key);
for (var i = 0; i < 16; i++) {
keyBytes[i] = keyData[i % keyData.length];
}
var k = new Uint32Array(4);
for (var i = 0; i < 4; i++) {
k[i] = (keyBytes[i * 4] << 24) | (keyBytes[i * 4 + 1] << 16) |
(keyBytes[i * 4 + 2] << 8) | keyBytes[i * 4 + 3];
}
var DELTA = 0x9e3779b9;
function teaEncrypt(v0, v1) {
var sum = 0;
for (var i = 0; i < 32; i++) {
sum = (sum + DELTA) >>> 0;
v0 = (v0 + (((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >>> 5) + k[1]))) >>> 0;
v1 = (v1 + (((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >>> 5) + k[3]))) >>> 0;
}
return [v0, v1];
}
var paddedLength = Math.ceil(input.length / 8) * 8;
var padded = new Uint8Array(paddedLength);
padded.set(input);
for (var i = 0; i < paddedLength; i += 8) {
var v0 = (padded[i] << 24) | (padded[i + 1] << 16) | (padded[i + 2] << 8) |
padded[i + 3];
var v1 = (padded[i + 4] << 24) | (padded[i + 5] << 16) |
(padded[i + 6] << 8) | padded[i + 7];
_a = teaEncrypt(v0, v1), v0 = _a[0], v1 = _a[1];
padded[i] = (v0 >>> 24) & 0xFF;
padded[i + 1] = (v0 >>> 16) & 0xFF;
padded[i + 2] = (v0 >>> 8) & 0xFF;
padded[i + 3] = v0 & 0xFF;
padded[i + 4] = (v1 >>> 24) & 0xFF;
padded[i + 5] = (v1 >>> 16) & 0xFF;
padded[i + 6] = (v1 >>> 8) & 0xFF;
padded[i + 7] = v1 & 0xFF;
}
if (input.length < paddedLength) {
var newInput = new Uint8Array(paddedLength);
newInput.set(input);
input = newInput;
}
for (var i = 0; i < paddedLength; i++) {
input[i] = padded[i];
}
return input;
}
异或+tea
div.js粘进控制台运行

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;___Key = 'K0meji_K0ishi';
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;___Key.toString = function() {
return 'Komeji Satori';
}
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;var Ori = console.log;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;console.log = function(...args) {
for (var i = 0; i < args.length; i++) {
if (args[i] == ___Key) {
args[i] = 'Komeji Satori';
}
}
Ori(...args);
}
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;___Key = 'K0meji_K0ishi';
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;___Key.toString = function() {
return 'Komeji Satori';
}
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;var Ori = console.log;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;console.log = function(...args) {
for (var i = 0; i < args.length; i++) {
if (args[i] == ___Key) {
args[i] = 'Komeji Satori';
}
}
Ori(...args);
}
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
key被换成了K0meji_K0ishi
写脚本解密
def tea_decrypt(v0, v1, k):
DELTA = 0x9e3779b9
sum_ = DELTA * 32
for _ in range(32):
v1 = (v1 - (((v0 << 4) + k[2]) ^ (v0 + sum_) ^ ((v0 >> 5) + k[3]))) & 0xFFFFFFFF
v0 = (v0 - (((v1 << 4) + k[0]) ^ (v1 + sum_) ^ ((v1 >> 5) + k[1]))) & 0xFFFFFFFF
sum_ = (sum_ - DELTA) & 0xFFFFFFFF
return v0, v1
ans = [94, 49, 141, 165, 142, 18, 244, 41, 100, 131, 44, 13, 99, 120, 148, 85, 226, 180, 172, 152, 204, 85, 244, 48]
key = 'K0meji_K0ishi'
key_bytes = [ord(c) for c in key]
step1 = [ans[i] ^ key_bytes[i % len(key_bytes)] for i in range(len(ans))]
key_16 = [key_bytes[i % len(key_bytes)] for i in range(16)]
k = [
(key_16[0] << 24) | (key_16[1] << 16) | (key_16[2] << 8) | key_16[3],
(key_16[4] << 24) | (key_16[5] << 16) | (key_16[6] << 8) | key_16[7],
(key_16[8] << 24) | (key_16[9] << 16) | (key_16[10] << 8) | key_16[11],
(key_16[12] << 24) | (key_16[13] << 16) | (key_16[14] << 8) | key_16[15]
]
step2 = []
for i in range(0, len(step1), 8):
v0 = (step1[i] << 24) | (step1[i + 1] << 16) | (step1[i + 2] << 8) | step1[i + 3]
v1 = (step1[i + 4] << 24) | (step1[i + 5] << 16) | (step1[i + 6] << 8) | step1[i + 7]
decrypted_v0, decrypted_v1 = tea_decrypt(v0, v1, k)
step2.extend([
(decrypted_v0 >> 24) & 0xFF,
(decrypted_v0 >> 16) & 0xFF,
(decrypted_v0 >> 8) & 0xFF,
decrypted_v0 & 0xFF,
(decrypted_v1 >> 24) & 0xFF,
(decrypted_v1 >> 16) & 0xFF,
(decrypted_v1 >> 8) & 0xFF,
decrypted_v1 & 0xFF
])
step3 = step2.copy()
if len(step3) >= 4:
step3[0] ^= 0x12
step3[1] ^= 0x34
step3[2] ^= 0x56
step3[3] ^= 0x78
flag_bytes = bytes(step3)
print("flag:", flag_bytes)
flag: b’flag{JS_1s_V3rY_dyN4M1C}’



3948

被折叠的 条评论
为什么被折叠?



