Đề bài

Giải
Bài này cho mình một file ELF 64-bit và một đoạn text bị mã hóa khá nặng, đầu tiên mình sẽ sử dụng IDA để dịch ngược

Đầu tiên chương trình sẽ mở file flag.txt ra và lưu vào biến flag (mình đổi tên cho dễ nhìn), và kiểm tra xem flag có tồn tại không
flag = fopen("flag.txt", "r");
if ( !flag )
{
fwrite("Error: file ./flag.txt not found\n", 1uLL, 0x21uLL, stderr);
exit(1);
}
Tiếp tục là một cái kiểm tra nữa thôi, không quan trọng
::flag = malloc(flag_size);
v6 = fread(::flag, 1uLL, flag_size, flag);
if ( v6 <= 0 )
exit(0);
Và cuối cùng, đoạn quan trọng nhất là encode flag
v3 = flag;
fclose(flag);
encode(v3);
Ở đây mình vào hàm encode và tiến hành dịch ngược
__int64 encode()
{
__int64 result; // rax
unsigned int Value; // [rsp+0h] [rbp-10h]
int v2; // [rsp+4h] [rbp-Ch]
unsigned int v3; // [rsp+8h] [rbp-8h]
char v4; // [rsp+Fh] [rbp-1h]
unsigned __int8 v5; // [rsp+Fh] [rbp-1h]
while ( *(_DWORD *)flag_index < flag_size )
{
v4 = lower((unsigned int)*((char *)flag + *(int *)flag_index));
if ( v4 == 32 )
{
v4 = -123;
}
else if ( v4 > 47 && v4 <= 57 )
{
v4 += 75;
}
v5 = v4 - 97;
if ( v5 > 0x24u )
badChars = 1;
if ( v5 != 36 )
v5 = abs32(((char)v5 + 18) % 36);
v3 = indexTable[(char)v5];
v2 = indexTable[(char)v5 + 1];
while ( (int)v3 < v2 )
{
Value = getValue(v3);
save(Value);
++v3;
}
++*(_DWORD *)flag_index;
}
while ( 1 )
{
result = (unsigned int)remain;
if ( remain == 7 )
break;
save(0LL);
}
return result;
}
Script
from pathlib import Path
secret = bytes([
0x8B,0xAA,0x2E,0xEE,0xE8,0xBB,0xAE,0x8E,0xBB,0xAE,
0x3A,0xEE,0x8E,0xEE,0xA8,0xEE,0xAE,0xE3,0xAA,
0xE3,0xAE,0xBB,0x8B,0xAE,0xB8,0xEA,0xAE,0x2E,
0xBA,0x2E,0xAE,0x8A,0xEE,0xA3,0xAB,0xA3,0xBB,0xBB,
0x8B,0xBB,0xB8,0xAE,0xEE,0x2A,0xEE,0x2E,0x2A,0xB8,
0xAA,0x8E,0xAA,0x3B,0xAA,0x3B,0xBA,0x8E,0xA8,0xEB,
0xA3,0xA8,0xAA,0x28,0xBB,0xB8,0xAE,0x2A,0xE2,
0xEE,0x3A,0xB8
] + [0]*0x1A)
idx = [0x0,0x4,0x12,0x28,0x3C,0x52,0x64,0x78,0x8E,0x9E,0xB4,
0xC8,0xDA,0xEA,0xFC,0x10E,0x11E,0x134,0x148,0x15A,
0x16A,0x172,0x180,0x18C,0x19A,0x1AA,0x1BC,0x1C8,
0x1D6,0x1E0,0x1EA,0x1F0,0x200,0x20A,0x216,0x222,
0x230,0x234]
def get_bit(i):
return (secret[i//8] >> (7 - (i%8))) & 1
codes = {y:[get_bit(idx[y]+k) for k in range(idx[y+1]-idx[y])] for y in range(len(idx)-1)}
END="_"
trie={}
for y,pat in codes.items():
node=trie
for bt in pat:
node=node.setdefault(bt,{})
node[END]=y
data = Path("output").read_bytes()
stream=[]
for b in data:
for k in range(7,-1,-1):
stream.append((b>>k)&1)
ys=[]
node=trie
i=0
while i < len(stream):
bt = stream[i]
if bt not in node:
if all(x==0 for x in stream[i:]):
break
raise RuntimeError(f"Decode error at bit {i}")
node=node[bt]
i+=1
if END in node:
ys.append(node[END])
node=trie
def y_to_char(y):
if y==36: return ' '
x=(y - 18) % 36
return chr(ord('a')+x) if x<=25 else chr(ord('0')+(x-26))
flag="".join(y_to_char(y) for y in ys)
print(flag)
Flag
Flag: t1m3f1i3500000000000f9ee1180
'WriteUp > Forensics' 카테고리의 다른 글
| 1985 - BuckeyeCTF 2025 (0) | 2025.11.09 |
|---|---|
| [Forensics] Please recover my files - Dreamhack (0) | 2025.11.04 |
| Corrupted file - picoCTF (0) | 2025.11.04 |
| Flag in Flame - picoCTF (0) | 2025.11.04 |
| Hidden in plainsight - picoCTF (0) | 2025.11.04 |
