前言
之前写的,一直没发,留个记录吧,万一哪天记录掉了起码在csdn有个念想
1.喵喵喵的flag碎了一地
查壳,丢进去64位中,查看主函数
第一步先查看字符串
第二步骤再找出函数
第三步在找出第第二步的函数里进行交叉应用
进行拼接出来
flag{My_fl@g_h4s_br0ken_4parT_Bu7_Y0u_c@n_f1x_1t!}
2.聪明的信使
脱壳查壳,拖进ida64里
看加密逻辑
发现加密逻辑
该函数遍历输入字符串中的每个字符,并根据其是否为大写字母或小写字母应用不同的加密逻辑。具体来说:
- 如果字符是小写字母(ASCII值在97到122之间),则将其转换为相对于'a'的索引(即减去97),加上偏移量
a2
,然后对26取模(以确保结果仍然在字母范围内),最后再将结果转换回ASCII值。 - 如果字符是大写字母(ASCII值在65到90之间),则执行类似的转换,但相对于'A'(即减去65)。
- 非字母字符保持不变。
其实也就是凯撒加密
def decrypt_caesar_cipher(encrypted_str, shift):
decrypted_str = []
for char in encrypted_str:
if 'a' <= char <= 'z': # 小写字母
decrypted_char = chr((ord(char) - ord('a') - shift) % 26 + ord('a'))
elif 'A' <= char <= 'Z': # 大写字母
decrypted_char = chr((ord(char) - ord('A') - shift) % 26 + ord('A'))
else: # 非字母字符保持不变
decrypted_char = char
decrypted_str.append(decrypted_char)
return ''.join(decrypted_str)
# 尝试所有可能的偏移值
encrypted_message = "oujp{H0d_TwXf_Lahyc0_14_e3ah_Rvy0ac@wc!}"
for shift_value in range(26):
decrypted_message = decrypt_caesar_cipher(encrypted_message, shift_value)
print(f"移位值 {shift_value}: {decrypted_message}")
找到flag
flag{Y0u_KnOw_Crypt0_14_v3ry_Imp0rt@nt!}
3.给阿姨倒一杯卡布奇诺
进入主函数
分析一波
结合题目,应该就是TEA/XTEA/XXTEA加密算法的一种
encrypt函数
OKK,是一个魔改的TEA,而且改的地方有点多
#include <stdio.h>
#include <stdint.h>
void decrypt(uint32_t* v, uint32_t* k, uint32_t* d) {
uint32_t v0 = v[0], v1 = v[1], i;
uint32_t delta = 0x6E75316C;
uint32_t sum = delta * 32;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < 32; i++) {
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) ^ (sum + (31 - i));
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) ^ (sum + (31 - i));
sum -= delta;
}
v[0] = v0 ^ d[0];
v[1] = v1 ^ d[1];
}
char* change(uint32_t num, char* word) {
for (int k = 0; k < 4; ++k) {
char ch = (num >> (k * 8)) & 0xFF;
word[k] = ch;
}
return word;
}
int main() {
uint32_t enc[] = { 0x5F797274, 0x64726168, 0x9B28ED45, 0x145EC6E9, 0x5B27A6C3, 0xE59E75D5, 0xE82C2500, 0xA4211D92, 0xCD8A4B62, 0xA668F440 };
uint32_t key[] = { 0x65766967, 0x756F795F, 0x7075635F, 0x6165745F };
char flag[33];
int flag_word = 0;
for (int i = 1; i < 5; ++i) {
uint32_t v[2] = { enc[i * 2], enc[i * 2 + 1] };
uint32_t d[2] = { enc[i * 2 - 2], enc[i * 2 - 1] };
decrypt(v, key, d);
/*printf("解密后的数据:%x %x\n", v[0], v[1]);
解密后的数据:62333331 34656666
解密后的数据:32643130 30613332
解密后的数据:35383332 63303964
解密后的数据:63316635 37373361*/
for (int j = 0; j < 2; j++) {
char temp[5];
change(v[j], temp);
for (int k = 0; k < 4; k++) {
flag[flag_word++] = temp[k];
}
}
}
flag[32] = '\0';
printf("XYCTF{%s}\n", flag);
return 0;
}
输出
XYCTF{133bffe401d223a02385d90c5f1ca377}
4.你真的是大学生吗
打开发现是ms-dos版本的语言
依然ida打开
源代码
public start
seg001:0000 start proc near
seg001:0000 mov ax, seg dseg
seg001:0003 mov ds, ax
seg001:0005 assume ds:dseg
seg001:0005 lea dx, unk_10000
seg001:0009 mov ah, 9
seg001:000B int 21h ; DOS - PRINT STRING
seg001:000B ; DS:DX -> string terminated by "$"
seg001:000D lea dx, unk_1002D
seg001:0011 mov ah, 0Ah
seg001:0013 int 21h ; DOS - BUFFERED KEYBOARD INPUT
seg001:0013 ; DS:DX -> buffer
seg001:0015 lea dx, unk_10010
seg001:0019 mov ah, 9
seg001:001B int 21h ; DOS - PRINT STRING
seg001:001B ; DS:DX -> string terminated by "$"
seg001:001D xor cx, cx
seg001:001F xor ax, ax
seg001:0021 mov cl, byte_1002E
seg001:0025 mov si, 2Fh ; '/'
seg001:0028 mov al, [si]
seg001:002A add si, cx
seg001:002C
seg001:002C loc_1007C: ; CODE XREF: start+37↓j
seg001:002C sub si, 1
seg001:002F xor [si], al
seg001:0031 mov al, [si]
seg001:0033 dec cx
seg001:0034 cmp cx, 0
seg001:0037 jnz short loc_1007C
seg001:0039 lea si, unk_1002F
seg001:003D lea di, unk_10019
seg001:0041
seg001:0041 loc_10091: ; CODE XREF: start+50↓j
seg001:0041 mov al, [si]
seg001:0043 mov bl, [di]
seg001:0045 add si, 1
seg001:0048 inc di
seg001:0049 cmp al, bl
seg001:004B jnz short loc_100AA
seg001:004D cmp cx, 0
seg001:0050 jnz short loc_10091
seg001:0052 lea dx, unk_10013
seg001:0056 mov ah, 9
seg001:0058 int 21h ; DOS - PRINT STRING
seg001:0058 ; DS:DX -> string terminated by "$"
seg001:005A
seg001:005A loc_100AA: ; CODE XREF: start+4B↑j
seg001:005A mov ah, 4Ch
seg001:005C int 21h ; DOS - 2+ - QUIT WITH EXIT CODE (EXIT)
seg001:005C start endp ; AL = exit code
seg001:005C
seg001:005C seg001 ends
seg001:005C
seg001:005C
seg001:005C end start
然后转换为伪代码
自己写的伪代码
dx = input string:$
cx ^= cx
ax ^= ax
cl = 0
si = 0x2F
al = 0
si += cx
for i in range(cx):
si -= 1
si ^= al
al = si地址对应的数
si = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00]
di = [0x76, 0x0E, 0x77, 0x14, 0x60, 0x06, 0x7D, 0x04, 0x6B, 0x1E,
0x41, 0x2A, 0x44, 0x2B, 0x5C, 0x03, 0x3B, 0x0B, 0x33, 0x05]
#逐位判断
al = si地址对应的数
bl = di地址对应的数
si += 1
di++
if al == bl:
结束
if cx == 0:
继续循环
dx = $Yes$
解密函数
def decrypt_xor_cipher(encrypted_array):
decrypted_array = []
prev_char = 0
for char in encrypted_array:
original_char = char ^ prev_char
decrypted_array.append(chr(original_char))
prev_char = char
return ''.join(decrypted_array)
encrypted_array = [0x76, 0x0E, 0x77, 0x14, 0x60, 0x06, 0x7D, 0x04, 0x6B, 0x1E, 0x41, 0x2A, 0x44, 0x2B, 0x5C, 0x03, 0x3B, 0x0B,0x33, 0x05]
original_array = decrypt_xor_cipher(encrypted_array)
print("Original array:", original_array)
输出
8086,emmmmm这应该就是汇编代码无疑了
XYCTF{you_know_8086}
5.ez_language
打开,拖到ida32里面
主函数没有什么东西
打开搜索字符串
提示可能为base64编码
加密算法可能是RC4或者是AES
查找密钥与密文
这两个特征有点像
拿去RC4和AES一下
打开赛博厨子
密文qBr4adaGb8kVFQpPVFMcwWQRybbInjf4Q9Iu+f6k9Nw=
RZy/zVEWMFxaCbzChAg8x26XZYr51rNVnM+zBoBp3gya93L9QQXpFRin1JE33vyx
密钥key
welcometoabctf!!
welcometoxyctf!!
RC4应该不行,用AES
发现是一个fakeflag
尝试另一个
6.ezmath
py解包一下
改一下,然后丢进pycdc里
整理一下代码
(((((((((((((((((((((( flag[23] * flag[23] ) + ( flag[12] * flag[12] ) + ( flag[1] * flag[1] ) - ( flag[24] * 222 )) + ( flag[22] * flag[22] ) + ( flag[31] * flag[31] ) + ( flag[26] * flag[26] ) - ( flag[9] * 178 ) - ( flag[29] * 232 )) + ( flag[17] * flag[17] ) - ( flag[23] * 150 ) - ( flag[6] * 226 ) - ( flag[7] * 110 )) + ( flag[19] * flag[19] ) + ( flag[2] * flag[2] ) - ( flag[0] * 176 )) + ( flag[10] * flag[10] ) - ( flag[12] * 198 )) + ( flag[24] * flag[24] ) + ( flag[9] * flag[9] ) - ( flag[3] * 168 )) + ( flag[8] * flag[8] ) - ( flag[2] * 134 )) + ( flag[14] * flag[14] ) - ( flag[13] * 170 )) + ( flag[4] * flag[4] ) - ( flag[10] * 142 )) + ( flag[27] * flag[27] ) + ( flag[15] * flag[15] ) - ( flag[15] * 224 )) + ( flag[16] * flag[16] ) - ( flag[11] * 230 ) - ( flag[1] * 178 )) + ( flag[28] * flag[28] ) - ( flag[5] * 246 ) - ( flag[17] * 168 )) + ( flag[30] * flag[30] ) - ( flag[21] * 220 ) - ( flag[22] * 212 ) - ( flag[16] * 232 )) + ( flag[25] * flag[25] ) - ( flag[4] * 140 ) - ( flag[31] * 250 ) - ( flag[28] * 150 )) + ( flag[11] * flag[11] ) + ( flag[13] * flag[13] ) - ( flag[14] * 234 )) + ( flag[7] * flag[7] ) - ( flag[8] * 174 )) + ( flag[3] * flag[3] ) - ( flag[25] * 242 )) + ( flag[29] * flag[29] ) + ( flag[5] * flag[5] ) - ( flag[30] * 142 ) - ( flag[26] * 170 ) - ( flag[19] * 176 )) + ( flag[0] * flag[0] ) - ( flag[27] * 168 )) + ( flag[20] * flag[20] ) - ( flag[20] * 212 )) + ( flag[21] * flag[21] ) + ( flag[6] * flag[6] ) + ( flag[18] * flag[18] ) - ( flag[18] * 178 )) + 297412 == 0
像这种求解方程一般用z3来解决
但是观察到每一个flag[i]都有(flag[i]*flag[i])-(flag[i]*num)
那就稍微先整理一下num吧
经过一顿手动整理:
diff = [176,178,134,168,140,246,226,110,174,178,142,230,198,170,234,224,232,168,178,176,212,220,212,150,222,242,170,168,150,232,142,250]
XYCTF{q7WYGscUuptTYXjnjKoyUTKtG}
7.ez_rand
进入主页面
int __fastcall main(int argc, const char **argv, const char **envp)
{
unsigned __int64 v3; // rbx
unsigned __int16 v4; // ax
int v5; // edi
__int64 v6; // rsi
int v7; // eax
int v9[7]; // [rsp+20h] [rbp-50h]
char v10; // [rsp+3Ch] [rbp-34h]
__int16 v11; // [rsp+3Dh] [rbp-33h]
__int128 v12; // [rsp+40h] [rbp-30h]
__int64 v13; // [rsp+50h] [rbp-20h]
int v14; // [rsp+58h] [rbp-18h]
__int16 v15; // [rsp+5Ch] [rbp-14h]
char v16; // [rsp+5Eh] [rbp-12h]
v13 = 0i64;
v12 = 0i64;
v14 = 0;
v15 = 0;
v16 = 0;
sub_140001020("请输入flag:");
sub_140001080("%s");
v9[0] = -362017699;
v11 = 0;
v3 = -1i64;
v9[1] = 888936774;
v9[2] = 119759538;
v9[3] = -76668318;
v9[4] = -1443698508;
v9[5] = -2044652911;
v9[6] = 1139379931;
v10 = 77;
do
++v3;
while ( *((_BYTE *)&v12 + v3) );
v4 = time64(0i64);
srand(v4);
v5 = 0;
if ( v3 )
{
v6 = 0i64;
do
{
v7 = rand();
if ( (*((_BYTE *)&v12 + v6) ^ (unsigned __int8)(v7
+ ((((unsigned __int64)(2155905153i64 * v7) >> 32) & 0x80000000) != 0i64)
+ ((int)((unsigned __int64)(2155905153i64 * v7) >> 32) >> 7))) != *((_BYTE *)v9 + v6) )
{
sub_140001020("Error???\n");
exit(0);
}
++v5;
++v6;
}
while ( v5 < v3 );
}
sub_140001020("Right???\n");
system("pause");
return 0;
}
分析通过随机数种子与时间戳就能够爆破出其flag
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
const unsigned char enc[] = {0x5D,0x0C,0x6C,0xEA,0x46,0x19,0xFC,0x34,0xB2,0x62,0x23,0x07,0x62,0x22,0x6E,0xFB,0xB4,0xE8,0xF2,0xA9,0x91,0x12,0x21,0x86,0xDB,0x8E,0xE9,0x43,0x4D};
int main(){
char ans[0x100]={0};
for(int i=0;i<=0xFFFF;i++){
srand(i);
for(int i=0;i<29;i++){
ans[i] = enc[i]^(rand()%0xFF);
}
if(strncmp(ans,"XYCTF",5)==0)break;
if(strncmp(ans,"xyctf",5)==0)break;
if(strncmp(ans,"flag",4)==0)break;
}
printf(ans);
return 0;
}
输出一下
XYCTF{R@nd_1s_S0_S0_S0_easy!}
8.砸核桃
查壳
需要进行脱壳
ida反编译结果是简单异或
数据:
byte_402130[v4 % 16]=this_is_not_flag
dword_402150[v4]=[0x12, 0x04, 0x08, 0x14, 0x24, 0x5C, 0x4A, 0x3D, 0x56, 0x0A,0x10, 0x67, 0x00, 0x41, 0x00, 0x01, 0x46, 0x5A, 0x44, 0x42,0x6E, 0x0C, 0x44, 0x72, 0x0C, 0x0D, 0x40, 0x3E, 0x4B, 0x5F,0x02, 0x01, 0x4C, 0x5E, 0x5B, 0x17, 0x6E, 0x0C, 0x16, 0x68,0x5B, 0x12, 0x48]
对这个写一个简单的脚本
# 密钥(假设是 "this_is_not_flag" 的前16个字符)
key = b'this_is_not_flag'
# 加密数据
encrypted_data = [
0x12, 0x04, 0x08, 0x14, 0x24, 0x5C, 0x4A, 0x3D,
0x56, 0x0A, 0x10, 0x67, 0x00, 0x41, 0x00, 0x01,
0x46, 0x5A, 0x44, 0x42, 0x6E, 0x0C, 0x44, 0x72,
0x0C, 0x0D, 0x40, 0x3E, 0x4B, 0x5F, 0x02, 0x01,
0x4C, 0x5E, 0x5B, 0x17, 0x6E, 0x0C, 0x16, 0x68,
0x5B, 0x12, 0x48
]
def xor_decrypt(data, key):
"""解密函数,使用给定的密钥对数据进行XOR操作"""
decrypted_data = bytearray()
key_length = len(key)
for i in range(len(data)):
# 对每个数据字节与相应的密钥字节执行XOR操作
decrypted_data.append(data[i] ^ key[i % key_length])
return decrypted_data
# 执行解密
decrypted_bytes = xor_decrypt(encrypted_data, key)
# 尝试将解密后的字节转换为字符串,并打印结果
try:
decrypted_string = decrypted_bytes.decode('utf-8')
print("Decrypted string:", decrypted_string)
except UnicodeDecodeError:
# 如果解密后的内容不能被正确解码为UTF-8字符串,则直接输出字节序列
print("Decrypted bytes:", decrypted_bytes)
或者是一个更简单的脚本
a = [
0x12, 0x04, 0x08, 0x14, 0x24, 0x5C, 0x4A, 0x3D,
0x56, 0x0A, 0x10, 0x67, 0x00, 0x41, 0x00, 0x01,
0x46, 0x5A, 0x44, 0x42, 0x6E, 0x0C, 0x44, 0x72,
0x0C, 0x0D, 0x40, 0x3E, 0x4B, 0x5F, 0x02, 0x01,
0x4C, 0x5E, 0x5B, 0x17, 0x6E, 0x0C, 0x16, 0x68,
0x5B, 0x12, 0x48
]
b = 'this_is_not_flag'
c = ''
for i in range(len(a)):
c += chr(a[i] ^ ord(b[i % len(b)]))
print(c)
9.ez_enc
查壳脱壳查看主函数
int __fastcall main_0(int argc, const char **argv, const char **envp)
{
signed int i; // [rsp+44h] [rbp+24h]
int j; // [rsp+64h] [rbp+44h]
j___CheckForDebuggerJustMyCode(&unk_140023008, argv, envp);
sub_1400111A4(&unk_14001ACB0);
sub_1400111A4(&unk_14001AE60);
sub_1400111A4(&unk_14001AF20);
sub_1400111A4(&unk_14001B1A0);
sub_1400111A4(&unk_14001B290);
sub_1400111A4(&unk_14001B640);
sub_1400111A4(&unk_14001AE18);
sub_14001109B(&unk_14001BA14, Str);//输入
for ( i = 0; i < (int)(j_strlen(Str) - 1); ++i )//加密
Str[i] = aImouto[i % 6] ^ (Str[i + 1] + (unsigned __int8)Str[i] % 20);
for ( j = 0; j < (int)j_strlen(Str); ++j )
{ //判断
if ( Str[j] != byte_14001E008[j] )
{
sub_1400111A4("Wrong");
return 0;
}
}
sub_1400111A4("Right,but where is my Imouto?\n");
return 0;
}
分析一波
数组的值
0x27, 0x24, 0x17, 0x0B, 0x50, 0x03, 0xC8, 0x0C, 0x1F, 0x17,
0x36, 0x55, 0xCB, 0x2D, 0xE9, 0x32, 0x0E, 0x11, 0x26, 0x02,
0x0C, 0x07, 0xFC, 0x27, 0x3D, 0x2D, 0xED, 0x35, 0x59, 0xEB,
0x3C, 0x3E, 0xE4, 0x7D
要异或的数
IMouto
但是尝试简单的异或脚本似乎不能完成解密过程,所以我们尝试用z3求解器进行完成
from z3 import *
# 已知密文
enc = [
0x27, 0x24, 0x17, 0x0B, 0x50, 0x03, 0xC8, 0x0C, 0x1F, 0x17,
0x36, 0x55, 0xCB, 0x2D, 0xE9, 0x32, 0x0E, 0x11, 0x26, 0x02,
0x0C, 0x07, 0xFC, 0x27, 0x3D, 0x2D, 0xED, 0x35, 0x59, 0xEB,
0x3C, 0x3E, 0xE4, 0x7D
]
# 密钥
key = "IMouto"
def solve():
s = Solver()
# 创建变量数组
flag = [BitVec(f'flag_{i}', 8) for i in range(len(enc))]
# 添加约束条件
for i in range(len(enc)-1):
# 加密方程: enc[i] = key[i%6] ^ (next_char + curr_char%20)
s.add(enc[i] == ord(key[i%6]) ^ (flag[i+1] + (flag[i] % 20)))
# 最后一个字符的约束
s.add(enc[-1] == flag[-1])
# 添加可见字符约束 (ASCII 32-126)
for i in range(len(flag)):
s.add(flag[i] >= 32)
s.add(flag[i] <= 126)
# 检查是否有解
if s.check() == sat:
m = s.model()
result = ''
# 获取结果
for i in range(len(flag)):
c = m[flag[i]].as_long()
result += chr(c)
return result
else:
return "No solution found"
print(solve())
输出
flag{!_r3ea11y_w4nt_@_cu7e_s1$ter}
10.何须相思煮余年
常见指令
00CD1790 55 push ebp
00CD1791 8B EC mov ebp,esp
00CD1793 81 EC C0 00 00 00 sub esp,0C0h
00CD1799 53 push ebx
00CD179A 56 push esi
00CD179B 57 push edi
00CD179C 8D BD 40 FF FF FF lea edi,[ebp-0C0h]
00CD17A2 B9 30 00 00 00 mov ecx,30h
00CD17A7 B8 CC CC CC CC mov eax,0CCCCCCCCh
00CD17AC F3 AB rep stos dword ptr es:[edi]
开辟栈帧以及security cookie
--------------------------------------------------------------------
--------------------------------------------------------------------
printf("Hello World\n");
00CD17AE 68 30 6B CD 00 push offset string "Hello World\n" (0CD6B30h)
printf("Hello World\n");
00CD17B3 E8 5E FB FF FF call _printf (0CD1316h)
00CD17B8 83 C4 04 add esp,4 //堆栈平衡
return 0;
00CD17BB 33 C0 xor eax,eax
--------------------------------------------------------------------
--------------------------------------------------------------------
00CD17BD 5F pop edi
00CD17BE 5E pop esi
00CD17BF 5B pop ebx
00CD17C0 81 C4 C0 00 00 00 add esp,0C0h
00CD17C6 3B EC cmp ebp,esp
00CD17C8 E8 41 F9 FF FF call __RTC_CheckEsp (0CD110Eh)
00CD17CD 8B E5 mov esp,ebp
00CD17CF 5D pop ebp
00CD17D0 C3 ret
回收栈帧,堆栈平衡
push ebp
mov ebp, esp
sub esp, 0xa8
mov eax, [0x41404000]
xor eax, ebp
mov [ebp-0x4], eax
push 0x0
lea eax, [ebp-0xa0]
push eax
push dword 0xc0c7ff58
push dword 0x27
mov dword [ebp-0xa4], 0x0
jmp 0xf
loc_1:
mov ecx, [ebp-0xa4]
add ebp, [ebp-0xa0]
mov dword [ebp-0xa4], ecx
mov dword [ebp-0xa4], 0x27f
lea ebp, [ebp+0xf]
mov edx, [ebp-0xa4]
add edx, 0x80000003
cmp byte [ecx+0x5], 0x4a
sbb edx, 0xfc
add edx, 0x4285
jnz loc_2
mov ecx, [ebp-0xa4]
mov ecx, [ecx-0xa0]
mov eax, [ebp-0xa4]
sub eax, 0x3
add eax, 0x80400003
cmp byte [ecx+0x5], 0x49
sbb eax, 0xfc
add eax, 0x4183
jnz loc_3
mov edx, [ebp-0xa4]
mov ecx, [edx-0x40]
add ecx, [ebp-0xa4]
inc ecx
mov edx, [ebp-0xa4]
sub edx, [ebp-0x5c]
mov eax, [ebp-0xa4]
mov [ecx+edx*4], eax
jmp 0x38
loc_2:
mov ecx, [ebp-0xa4]
add edx, [ecx+0x5]
add edx, 0x80400003
cmp byte [ecx+0x5], 0x4a
sbb edx, 0xfc
add edx, 0x4283
jnz loc_4
mov ecx, [ebp-0xa4]
mov ecx, [ecx-0xa0]
mov eax, [ebp-0xa4]
sub eax, 0x3
add eax, 0x80400003
cmp byte [ecx+0x5], 0x49
sbb eax, 0xfc
add eax, 0x4183
jnz loc_5
mov edx, [ebp-0xa4]
mov ecx, [edx-0x40]
add ecx, [ebp-0xa4]
xor ecx, ebp
mov edx, [ebp-0xa4]
sub edx, [ebp-0x5c]
mov eax, [ebp-0xa4]
mov [ecx+edx*4], eax
jmp 0xf7
loc_3:
xor eax, eax
mov ecx, [ebp-0x4]
xor ecx, ebp
call 0x4
mov esp, ebp
pop ebp
ret
loc_4:
mov ecx, [ebp-0x4]
sub ecx, ebp
call 0x4
mov esp, ebp
pop ebp
ret
cyberchif from hex转成二进制 然后32bit拖进ida
然后32bit拖进ida里
转换为伪代码
写一个简单的异或解密脚本
enc = [88,88,134,87,74,118,318,101,59,92,480,60,65,41,770,110,73,31,918,39,120,27,1188,47,77,24,1352,44,81,23,1680,46,85,15,1870,66,91,16,4750]
for i in range(40):
if i % 4 == 1:
enc[i] += i
elif i % 4 == 2:
enc[i] /= i
elif i % 4 == 3:
enc[i] ^= i
elif i % 4 == 0:
enc[i] -= i
print(enc[i],end=",")
flag = [88,89,67,84,70,123,53,98,51,101,48,55,53,54,55,97,57,48,51,52,100,48,54,56,53,49,52,55,53,52,56,49,53,48,55,97,55,53,125]
for j in flag:
print(chr(j),end="")
输出一下
XYCTF{5b3e07567a9034d06851475481507a75}
11.what's this ?
打开发现是lua
Lua语言,直接在网上找反编译网站
保存在本地
翻到最下面,文件代码几千行,但是实际有用的也就后面的一小部分
function Xor(r0_198, r1_198)
-- line: [891, 916] id: 198
local r2_198 = r0_198
local r3_198 = r1_198
local r4_198 = ""
repeat
if r2_198 % 2 == r3_198 % 2 then
r4_198 = "0" .. r4_198
else
r4_198 = "1" .. r4_198
end
r2_198 = math.modf(r2_198 / 2)
r3_198 = math.modf(r3_198 / 2)
until r2_198 == 0 and r3_198 == 0
return tonumber(r4_198, 2)
end
value = ""
output = ""
i = 1
repeat
value = value .. string.char(Xor(string.byte(flag, i), 8) % 256)
i = i + 1
until string.len(flag) < i
for r3_0 = 1, 1000, 1 do
x = 3
y = x * 3
z = y / 4
w = z - 5
if w == 0 then
print("This line will never be executed")
end
end
for r3_0 = 1, string.len(flag), 1 do
temp = string.byte(value, r3_0)
temp = string.char(temp + 3)
output = output .. temp
end
result = output:rep(10)
invalid_list = {
1,
2,
3
}
for r3_0 = 1, 20, 1 do
table.insert(invalid_list, 4)
end
for r3_0 = 1, 50, 1 do
result = result .. "A"
table.insert(invalid_list, 4)
end
for r3_0 = 1, string.len(output), 1 do
temp = string.byte(output, r3_0)
temp = string.char(temp - 1)
end
for r3_0 = 1, 30, 1 do
result = result .. string.lower(output)
end
for r3_0 = 1, 950, 1 do
x = 3
y = x * 3
z = y / 4
w = z - 5
if w == 0 then
print("This line will never be executed")
end
end
for r3_0 = 1, 50, 1 do
x = -1
y = x * 4
z = y / 2
w = z - 3
if w == 0 then
print("This line will also never be executed")
end
end
require("base64")
obfuscated_output = to_base64(output)
obfuscated_output = string.reverse(obfuscated_output)
obfuscated_output = string.gsub(obfuscated_output, "g", "3")
obfuscated_output = string.gsub(obfuscated_output, "H", "4")
obfuscated_output = string.gsub(obfuscated_output, "W", "6")
invalid_variable = obfuscated_output:rep(5)
if obfuscated_output == "==AeuFEcwxGPuJ0PBNzbC16ctFnPB5DPzI0bwx6bu9GQ2F1XOR1U" then
print("You get the flag.")
else
print("F**k!")
end
致加密逻辑是,字符串异或异或8,再加三,经过base64加密,最后替换字符串(g->3;H->4;W->6)
逆向解密:
替换:==AeuFEcwxGPuJ0PBNzbC1WctFnPB5DPzI0bwxWbu9GQ2F1XOR1U
逆序:U1ROX1F2QG9ubWxwb0IzPD5BPnFtcW1CbzNBP0JuPGxwcEFueA==
base64解密:STN_Qv@onmlpoB3<>A>qmqmBo3A?Bn<lppAnx
再写一个脚本
a ='STN_Qv@onmlpoB3<>A>qmqmBo3A?Bn<lppAnx'
b =''
for i in range(len(a)):
b+=chr((ord(a[i])-3^8))
print(b)
XYCTF{5dcbaed781363fbfb7d8647c1aee6c}
12.trust_me
public static int image = 0x7f0800d8;
public static int loginbutton = 0x7f0800ed;
public static int password = 0x7f080148;
public static int username = 0x7f0801dc
对于这类apk的逆向,我们更推荐sql注入,毕竟是一个登录框,不然的话就是要分析RC4代码
拖到安卓模拟器中
XYCTF{And0r1d_15_V3ryEasy}
13.今夕是何年
发现是龙芯架构(着tama谁知道)
14.舔狗四部曲-相逢已是上上签
拖进DIE里 看DIE信息以为又nm来一道16位汇编题,但是IDA 16bit模式打不开,HxD打开一看"This program cannot be run in DOS mode",这不是我们亲爱的DOS头吗,那这题绝对不是16位汇编了啊,那八成是魔改DOS头了,那问题来了,为啥DIE读出来DOS头了没读出来PE头呢,010 启动!
是32位程序呢,拖进DIA里:
先是读进一个key,然后是一大坨比较,然后读入flag,通过key xxtea,最后和v6比较
先解决key的问题,用z3把他秒了:
from z3 import *
byte_422918 = [Int(f"char_{i}") for i in range(6)]
s = Solver()
s.add(
532 * byte_422918[5]
+ 829 * byte_422918[4]
+ 258 * byte_422918[3]
+ 811 * byte_422918[2]
+ 997 * byte_422918[1]
+ 593 * byte_422918[0]
== 292512
)
s.add(
576 * byte_422918[5]
+ 695 * byte_422918[4]
+ 602 * byte_422918[3]
+ 328 * byte_422918[2]
+ 686 * byte_422918[1]
+ 605 * byte_422918[0]
== 254496
)
s.add(
580 * byte_422918[5]
+ 448 * byte_422918[4]
+ 756 * byte_422918[3]
+ 449 * byte_422918[2]
+ (byte_422918[1] *(1 << 9))
+ 373 * byte_422918[0]
== 222479
)
s.add(
597 * byte_422918[5]
+ 855 * byte_422918[4]
+ 971 * byte_422918[3]
+ 422 * byte_422918[2]
+ 635 * byte_422918[1]
+ 560 * byte_422918[0]
== 295184
)
s.add(
524 * byte_422918[5]
+ 324 * byte_422918[4]
+ 925 * byte_422918[3]
+ 388 * byte_422918[2]
+ 507 * byte_422918[1]
+ 717 * byte_422918[0]
== 251887
)
s.add(
414 * byte_422918[5]
+ 495 * byte_422918[4]
+ 518 * byte_422918[3]
+ 884 * byte_422918[2]
+ 368 * byte_422918[1]
+ 312 * byte_422918[0] == 211260
)
for i in byte_422918:
s.add(i>=0)
s.add(i<=0xFF)
s.check()
print(s.model())
[char_1 = 89,
char_5 = 33,
char_4 = 70,
char_0 = 88,
char_2 = 67,
char_3 = 84]
整理一下,key就是XYCTF!
,那flag也好说了,xxtea只要逆着算就能还原:
#include<stdio.h>
#include<stdint.h>
const char* key = "XYCTF!";
void enc(uint32_t *enc){
uint32_t sum = 0;
for(int i=0;i<12;i++)
{
sum -= 0x61C88647;
uint32_t v6 = (sum >> 2) & 5;
for (int j=0;j<8;++j)
{
uint32_t next = enc[(j+1)%8];
uint32_t last = enc[(j-1+8)%8];
enc[j] +=((last^key[v6^j&5])+(next^sum))^(((16*last)^(next>>3))+((4*next)^(last>>5)));
}
}
}
void re(uint32_t *enc){
uint32_t sum = -0x61C88647*12;
for(int i=0;i<12;i++){
uint32_t v6 = (sum >> 2) & 5;
for(int j=7;j>=0;j--){
uint32_t next = enc[(j+1)%8];
uint32_t last = enc[(j-1+8)%8];
enc[j] -=((last^key[v6^j&5])+(next^sum))^(((16*last)^(next>>3))+((4*next)^(last>>5)));
}
sum += 0x61C88647;
}
}
int main(){
uint32_t arr[] = {0x66697271,0x896E2285,0xC5188C1B,0x72BCFD03,0x538011CA,0x4DA146AC,0x86630D6B,0xF89797F0};
re(arr);
for(int i=0;i<8;i++){
printf("%X ",arr[i]);
}
printf("\n%s",arr);
return 0;
}
XYCTF{XXTEA_AND_Z3_1s_S0_easy!!}
15.馒头
这是经典的数据结构算法哈夫曼树
这个没写,看了大佬的手搓的哈夫曼树
然后就,根据字符顺序挨个把权重转化成字符即可
然后就解出来了
XYCTF{xaf1svut7rojh3de0}