
Incognito 4.0
Nguồn ở đây nhá các bạn: 💀👆👆👆💀
Xin chào mọi người đến với giải đợt này, giải này team tôi bắt đầu có thêm các nhân tố bí mới chơi..👾 Vẫn như thường lệ thì sau đây sẽ là các nhiệm vụ về mảng RE. Bắt đầu thôi….🐈⬛
Lưu ý là các giải tới tôi sẽ viết qua ý tưởng mấy bài dễ làm nếu tôi làm để có thể là nơi tham khảo của mấy bạn team tui hoặc những bạn mới khác.
1: Meow
Đối với thử thách đầu tiên và dễ òm đã có hơn 200 team giải ra thì bài này mở file đó ra trên phần mềm dịch ngược ví dụ như IDA pro.
Lúc đầu tôi đọc qua thì chương trình không có gì cả, tôi thầm nghĩ là chương trình thật vô nghĩa khi không có gì))). Sau đó tôi nhìn qua toàn bộ các phần của file, phần data, code,… thì phát hiện ra chương trình lưu trữ file string gồm các ký tự tạo flag cách nhau bằng 1 byte NULL.
Và xong thật dễ phải không nào👻
2: Rev This
Với chall này thì như thường lệ thì check file rồi đưa vào IDA check hàm main nó như nào:
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v4; // [rsp+8h] [rbp-88h]
int i; // [rsp+Ch] [rbp-84h]
int j; // [rsp+10h] [rbp-80h]
char v7[9]; // [rsp+17h] [rbp-79h]
__int64 v8[6]; // [rsp+20h] [rbp-70h] BYREF
__int64 v9[8]; // [rsp+50h] [rbp-40h] BYREF
v9[7] = __readfsqword(0x28u);
v4 = 0;
memset(v8, 0, 34);
*(__int64 *)((char *)&v8[4] + 2) = 0x100000000000000LL;
memset(v9, 0, 34);
*(__int64 *)((char *)&v9[4] + 2) = 0x100000000000000LL;
rand_str(v8, 41LL);
rand_str(v9, 41LL);
for ( i = 0; i <= 40; ++i )
v7[i] = *((_BYTE *)v9 + i) ^ *((_BYTE *)v8 + i);
for ( j = 0; j <= 40; ++j )
v4 += v7[j] - 4 * j;
message(v4);
return 0;
}
Hàm main của chương trình là đây.
Và tôi thắc mắc hàm message()
chắc khả năng nó đây:
__int64 __fastcall message(int a1)
{
int i; // [rsp+1Ch] [rbp-34h]
__int64 v3[4]; // [rsp+20h] [rbp-30h]
char v4; // [rsp+40h] [rbp-10h]
unsigned __int64 v5; // [rsp+48h] [rbp-8h]
v5 = __readfsqword(0x28u);
v3[0] = 0x6071B14091B0C06LL;
v3[1] = 0x70806031C1C061CLL;
v3[2] = 0xA0B1D0E0716031BLL;
v3[3] = 0x41C0E1B190A1D1DLL;
v4 = 18;
for ( i = 0; i <= 32; ++i )
putchar(a1 ^ *((char *)v3 + i));
return 0LL;
}
Như trên thì hàm message()
này sẽ putchar()
từng ký tự của flag ra cho mình.
Lợi dụng điều đó mà tôi không cần quan tâm đến phần trước của chương trình. Vì ta đã biết format của cờ là gì rồi vấn đề còn lại là xor với giá trị kia là ra thôi…
Và đây là solve của tôi bằng python:
from __ctf import *
a = ['06071B14091B0C06', '070806031C1C061C', '0A0B1D0E0716031B', '041C0E1B190A1D1D']
lst = []
for i in a:
for j in range(len(i),0,-2):
lst.append(int(i[j-2:j],16))
for i in lst:
print(chr(i^111),end='') # số 111 là lấy giá trị đầu tiên xor với ký tự i
Và nhận được flag…👉
3: AnotherRev
Tiếp đến là bài này khiến tôi mất thời gian thôi chứ bài này cũng dễ, chỉ là sử dụng z3 để làm thôi)))
Main của chương trình:
int __cdecl main(int argc, const char **argv, const char **envp)
{
read(0, &flag, 0x2BuLL);
if ( (unsigned int)fun() )
puts("Flag");
else
puts("Not flag");
return 0;
}
Hàm chính thật ngắn gọn và súc tích))).
Nhận thấy flag này có kích thước 0x2b tương đương với 43 ký tự.
Và chương trình chuyển đến kiểm tra flag bằng hàm fun()
trả về kiểu boolean đúng hoặc sai 1 hoặc 0. Nếu 1 thì chắc chắn rồi flag here….
Vào hàm fun()
thì ối dồi ôi, chương trình gồm 41 câu điều kiện và 1 câu lệnh gán.
_BOOL8 fun()
{
int v1; // [rsp+0h] [rbp-4h]
v1 = byte_405059 + byte_405068 == 109;
if ( byte_405059
+ byte_40505F
+ byte_405058
+ byte_405050
+ byte_40505F
+ byte_405065
+ byte_405062
+ byte_405049
+ byte_405065
+ byte_405068 == 706 )
++v1;
//.....
if ( byte_40504C
+ byte_405052
+ byte_405045
+ byte_405051
+ byte_40505D
+ byte_405065
+ byte_40504D
+ byte_405061
+ byte_405065
+ byte_405058
+ byte_405063
+ byte_40505C
+ byte_405062
+ byte_405066
+ byte_405061
+ flag == 1198 )
++v1;
if ( byte_40504E + byte_405064 + byte_40504C + byte_40504D + byte_405054 == 295 )
++v1;
return v1 == 42;
}
Tôi chỉ copy từng này thôi vì nó dài quá))) và đó cũng là lý do khiến tôi mất nhiều thời gian cho nó mà trong khi đó bài này không có gì cả))).
Nhận thấy nếu là flag thì tất cả các điều kiện phải đúng để giá trị của v1
cộng 1 sau mỗi câu điều kiện và câu lệnh gán đầu tiên cũng đúng để giá trị v1
lúc đầu bằng 1.
Cộng tổng vào bằng 42 là đúng flag…
các byte_...
thực chất ra là các ký tự của flag thôi… Dưới đây tôi giải thích luôn nè:
Đó như các bạn thấy thì các byte_...
được IDA nhận dạng là các bytes nằm gần nhau… chắc có ý đồ gì của tác giả khiến mình nhìn dối code thôi. Chứ nghĩ đơn giản nó là một mảng flag. Phần tử đầu tiên có tên là flag; phần tử thứ 2 là byte_405041
.v.v. Cứ như vậy là xong.
Còn lại là việc sử dụng các điều kiện đó để ra flag thôi. Với nhiều điều kiện này thì Z3 không ai khác là trợ thủ cực kỳ đắc lực đối với mọi các dân chơi RE))).
Copy và fix lại 1 hồi nửa tiết học của tôi ở trường🥲. Đây là lời giải của tôi:
from z3 import *
s = Solver()
flag = [BitVec(f'flag{i}', 8) for i in range(0,43)]
for i in range(1,43):
s.add(And(flag[i]>0, flag[i]<127))
s.add(flag[0] ==99)
s.add(flag[26] + flag[41] == 109)
s.add(flag[26] + flag[32] + flag[25] + flag[17] + flag[32] + flag[38] + flag[35] + flag[10] + flag[38] + flag[41] == 706)
s.add(flag[38] + flag[22] + flag[25] + flag[22] + flag[18] + flag[33] + flag[6] + flag[9] + flag[12] + flag[6] + flag[20] == 764)
s.add(flag[21] + flag[1] + flag[4] + flag[42] + flag[41] + flag[2] + flag[25] + flag[41] + flag[3] + flag[27] + flag[14] + flag[32] + flag[22] + flag[22] + flag[2] + flag[23] == 1395)
s.add(flag[25] + flag[8] + flag[14] + flag[32] + flag[34] + flag[15] + flag[31] + flag[26] + flag[11] + flag[35] + flag[24] == 753)
s.add(flag[2] + flag[18] + flag[8] + flag[6] == 261)
s.add(flag[9] + flag[25] + flag[32] + flag[26] + flag[11] + flag[39] + flag[30] + flag[30] + flag[13] + flag[22] == 666)
s.add(flag[15] + flag[39] + flag[22] == 300)
s.add(flag[22] + flag[33] + flag[41] + flag[36] + flag[32] + flag[24] + flag[29] + flag[8] + flag[2] + flag[9] + flag[14] + flag[33] + flag[30] + flag[26] + flag[5] == 933)
s.add(flag[37] + flag[13] + flag[34] + flag[41] + flag[21] + flag[23] + flag[6] + flag[27] + flag[33] + flag[32] + flag[35] + flag[3] + flag[9] + flag[40] + flag[19] + flag[22] == 1168)
s.add(flag[23] + flag[24] + flag[29] + flag[3] + flag[25] + flag[42] + flag[42] + flag[35] + flag[42] + flag[28] + flag[21] + flag[29] + flag[20] + flag[22] + flag[10] + flag[17] + flag[31] == 1375)
s.add(flag[36] + flag[19] + flag[26] + flag[30] + flag[39] + flag[20] + flag[31] == 409)
s.add(flag[39] + flag[3] + flag[33] + flag[17] + flag[26] + flag[12] + flag[17] + flag[29] + flag[1] + flag[28] + flag[29] == 765)
s.add(flag[21] + flag[25] + flag[19] + flag[25] + flag[26] + flag[29] + flag[39] + flag[5] + flag[14] + flag[39] + flag[28] + flag[24] == 902)
s.add(flag[5] + flag[41] == 178)
s.add(flag[28] + flag[30] + flag[26] + flag[38] + flag[24] + flag[32] + flag[15] + flag[15] + flag[15] + flag[32] + flag[27] + flag[11] + flag[13] + flag[17] + flag[34] + flag[4] + flag[32] + flag[28] + flag[2] + flag[32] == 1513)
s.add(flag[7] + flag[11] + flag[41] == 165)
s.add(flag[18] + flag[2] + flag[41] + flag[35] + flag[9] + flag[12] + flag[38] + flag[17] + flag[14] + flag[11] == 653)
s.add(flag[40] + flag[31] + flag[5] + flag[23] + flag[8] + flag[30] + flag[24] + flag[25] + flag[37] + flag[30] + flag[33] + flag[29] + flag[10] + flag[5] + flag[41] + flag[13] + flag[41] + flag[20] + flag[36] == 1266)
s.add(flag[29] + flag[39] + flag[22] + flag[39] + flag[27] + flag[25] + flag[3] + flag[33] == 711)
s.add(flag[40] + flag[2] + flag[12] + flag[10] + flag[5] + flag[16] + flag[2] + flag[10] + flag[36] + flag[22] + flag[20] + flag[26] + flag[24] + flag[41] + flag[1] + flag[20] + flag[40] == 1294)
s.add(flag[5] + flag[27] + flag[2] + flag[10] + flag[21] + flag[21] + flag[19] + flag[38] + flag[26] + flag[16] + flag[38] + flag[9] + flag[16] + flag[3] + flag[29] + flag[11] + flag[36] + flag[41] + flag[42] == 1485)
s.add(flag[31] + flag[17] == 100)
s.add(flag[23] + flag[14] + flag[6] + flag[42] + flag[36] + flag[17] + flag[24] + flag[8] + flag[1] + flag[16] + flag[7] + flag[6] + flag[16] == 945)
s.add(flag[13] + flag[1] + flag[40] + flag[23] + flag[19] + flag[33] + flag[4] + flag[1] + flag[2] + flag[37] + flag[25] + flag[26] + flag[23] + flag[34] + flag[9] + flag[5] == 1327)
s.add(flag[31] + flag[40] + flag[24] + flag[13] + flag[42] + flag[28] + flag[23] + flag[13] + flag[8] + flag[3] + flag[7] + flag[14] + flag[3] + flag[15] + flag[9] + flag[24] + 2 * flag[26] + flag[41] == 1370)
s.add(flag[22] + flag[30] + flag[3] + flag[21] + flag[31] + flag[41] == 426)
s.add(flag[11] + flag[36] + flag[19] + flag[16] + flag[8] + flag[28] + flag[20] + flag[13] + flag[12] + flag[10] + flag[22] + flag[41] + flag[4] + flag[39] + flag[4] + flag[22] + flag[17] + flag[27] == 1329)
s.add(flag[7] + flag[40] + flag[1] + flag[2] + flag[20] + flag[35] + flag[23] + flag[14] + flag[15] + flag[42] + flag[38] + flag[5] + flag[38] == 1199)
s.add(flag[20] + flag[13] + flag[11] + flag[27] + flag[12] + flag[28] + flag[29] + flag[7] + flag[35] + flag[15] + flag[5] + flag[7] + flag[13] + flag[1] + flag[28] + flag[24] + flag[7] + flag[42] + flag[4] == 1470)
s.add(flag[4] + flag[17] + flag[11] == 206)
s.add(flag[30] + flag[34] + flag[41] + flag[33] + flag[28] + flag[13] + flag[8] == 470)
s.add(flag[36] + flag[17] + flag[23] + flag[33] + flag[33] + flag[18] + flag[30] + flag[6] + flag[3] + flag[11] + flag[20] + flag[5] + flag[23] + flag[23] + flag[21] + flag[17] + flag[35] + flag[13] + flag[20] == 1302)
s.add(flag[42] + flag[6] + flag[15] + flag[32] + flag[38] + flag[10] + flag[40] + flag[28] + flag[11] + flag[35] + flag[35] == 936)
s.add(flag[6] + flag[10] + flag[5] == 234)
s.add(flag[2] + flag[35] + flag[38] + flag[40] + flag[3] + flag[19] + flag[33] + flag[41] + flag[27] + flag[4] + flag[32] + flag[34] + flag[34] == 1116)
s.add(flag[10] + flag[14] + flag[17] + flag[2] + flag[16] + flag[30] + flag[5] + flag[23] + flag[4] + flag[12] == 777)
s.add(flag[29] + flag[40] + flag[33] + flag[35] + flag[8] + flag[19] == 394)
s.add(flag[31] + flag[14] + flag[9] + flag[25] + flag[20] + flag[32] + flag[17] + flag[7] + flag[14] + flag[31] + flag[30] + flag[1] == 705)
s.add(flag[2] + flag[15] == 200)
s.add(flag[13] + flag[19] + flag[6] + flag[18] + flag[30] + flag[38] + flag[14] + flag[34] + flag[38] + flag[25] + flag[36] + flag[29] + flag[35] + flag[39] + flag[34] + flag[1] == 1198)
s.add(flag[15] + flag[37] + flag[13] + flag[14] + flag[21] == 295)
if s.check() == sat:
sol = []
for i in range(1,43):
sol.append(s.model().eval(flag[i]).as_long())
print(''.join([chr(int(c)) for c in sol]))
Cứ chạy là ra flag. Nếu làm truyền thống thì mất rất nhiều thời gian nhé các pro của tôi…
4: Gainme
Bài này là bài ở phần pwn nhưng tôi thấy thì nó thực chất là bài RE hay là nó có lỗi gì đó để có thể nhanh hơn.
Tôi cũng không biết nữa. Chạy file và đọc file thấy chương trình yêu cầu mình trải qua 3 cấp độ kiểm tra tương ứng với level. Các level sẽ tương ứng với hàm khác nhau để kiểm tra đầu vào của ta.
- Level 1: thì so sánh chuỗi
ICTF4
- Level 2: cũng so sánh chuỗi
dasDASQWgjtrkodsc
- Level 3: so sánh giá trị bằng với địa chỉ
0xDEADBEEF
- Level cuối thì input giá trị đầu vào chuyển nó thành số rồi tính toán theo 1 biểu thức mà giá trị của biểu thức này phải bằng 0 để không bị thoát chương trình.
Mục tiêu là thỏa mãn tất cả các level để không bị cash chương trình ở phần nào kể. Kết thúc thì sẽ đến phần đọc file flag.txt của máy nhà tổ chức)))..
Đó là tất cả ý tưởng. Và sau đây là solve của tôi cho các bạn tham khảo:
from pwn import *
r = remote("143.198.219.171", 5003)
payload = b'ICTF4'
r.sendline(payload)
payload1 = b'dasDASQWgjtrkodsc'
r.sendline(payload1)
payload2 = p32(0xDEADBEEF)
r.sendline(payload2)
payload3 = b'1'
r.sendline(payload3)
r.interactive() # để tương tác với shell
Như vậy kết thúc cái giải dễ này nhé👾. Cảm ơn mọi người đã đọc đến đây.