# [WRITEUP ISITDTU 2024]
---
## [Reverse Engineering]
## Name: RE01
:::info
:bulb: Đề bài cho 1 file PE 64 bit
:::
---
### :small_blue_diamond:**Link:https://drive.google.com/drive/folders/16vE3lMrlPTfzRRG9OqSMoKq8TAbABeKX?usp=sharing**
### :small_blue_diamond: **Time: 15/01/2025**
---
## :white_check_mark: **WRITEUP**
### 1. Tổng quan
- Đầu tiên, sử dụng CFF Explorer để phân tích và lấy được thông tin cơ bản của file như: file PE64bit.

- :bulb: IDA Pro là phương án tốt nhất để phân tích file PE này
### 2. Phân tích
- Sau khi load file vào IDA Pro thì ta nhận thấy chương trình khá đơn giản với một số hàm chính

*Các hàm quan trọng*
- Khi đọc hàm main thì có vẻ như chương trình yêu cầu người dùng nhập một mật khẩu và được hash bằng thuật toán SHA1.

*Hàm main()*
- Nhưng khi thử crack đoạn hash thì với những tool crack phổ biến thì không thể crack được và sau khi kiểm tra lại kỹ thì nhận thấy một hàm rất khả nghi.

*Hàm đáng ngờ*
-- Tlscallback() là hàm api của Microsoft có tác dụng chạy trước cả hàm main() còn về docs thì có thể tham khảo ở đây: https://hex-rays.com/blog/tls-callbacks
- Tiến hành kiểm tra hàm này

*Hàm Tlscallback()*
- Kiểm tra sub_140004000()
```
void __fastcall sub_140004000(__int64 a1, int a2, __int64 a3)
{
int v5; // esi
__int64 v6; // rdi
char *v7; // r13
char *v8; // rax
int v9; // r14d
__int64 v10; // rdx
int *v11; // rcx
__int64 v12; // rbx
__int64 *v13; // rax
int v14; // edx
char *v15; // r14
size_t v16; // rcx
char *v17; // rbx
__int64 v18; // rsi
_QWORD *v19; // rcx
_QWORD *v20; // rbx
__int64 v21; // rdx
char *v22; // rax
void *Block; // [rsp+20h] [rbp-E0h] BYREF
int v24; // [rsp+28h] [rbp-D8h]
__int128 Src[14]; // [rsp+30h] [rbp-D0h] BYREF
int v26; // [rsp+110h] [rbp+10h]
int v27; // [rsp+114h] [rbp+14h]
__int128 v28[8]; // [rsp+120h] [rbp+20h] BYREF
void *Buf1[2]; // [rsp+1A0h] [rbp+A0h] BYREF
__int64 v30; // [rsp+1B0h] [rbp+B0h]
__int128 v31; // [rsp+1B8h] [rbp+B8h]
char *v32; // [rsp+1C8h] [rbp+C8h]
v24 = a2;
if ( IsDebuggerPresent() ) -> Kiểm tra debugger
exit(0);
*(_OWORD *)Buf1 = 0i64;
v5 = 0;
v6 = 0i64;
v30 = 0i64;
// Load dữ liệu
Src[0] = (__int128)_mm_load_si128((const __m128i *)&xmmword_140007770);
Src[1] = (__int128)_mm_load_si128((const __m128i *)&xmmword_1400076D0);
Src[2] = (__int128)_mm_load_si128((const __m128i *)&xmmword_140007700);
Src[3] = (__int128)_mm_load_si128((const __m128i *)&xmmword_1400076C0);
Src[4] = (__int128)_mm_load_si128((const __m128i *)&xmmword_140007690);
Src[5] = (__int128)_mm_load_si128((const __m128i *)&xmmword_140007740);
Src[6] = (__int128)_mm_load_si128((const __m128i *)&xmmword_140007780);
Src[7] = (__int128)_mm_load_si128((const __m128i *)&xmmword_140007790);
Src[8] = (__int128)_mm_load_si128((const __m128i *)&xmmword_140007730);
Src[9] = (__int128)_mm_load_si128((const __m128i *)&xmmword_140007750);
Src[10] = (__int128)_mm_load_si128((const __m128i *)&xmmword_140007650);
Src[11] = (__int128)_mm_load_si128((const __m128i *)&xmmword_140007710);
Src[12] = (__int128)_mm_load_si128((const __m128i *)&xmmword_1400077A0);
Src[13] = (__int128)_mm_load_si128((const __m128i *)&xmmword_140007660);
v26 = 28;
v27 = 72;
v31 = 0i64;
v7 = (char *)operator new(0xE8ui64);
*(_QWORD *)&v31 = v7;
v32 = v7 + 232;
memmove(v7, Src, 0xE8ui64);
v8 = v7 + 232;
*((_QWORD *)&v31 + 1) = v7 + 232;
v9 = 0;
v10 = xmmword_14000B0F0;
v11 = (int *)Buf1[1];
if ( (_QWORD)xmmword_14000B0F0 )
{
v12 = 0i64;
do
{
v13 = &qword_14000B0E0;
if ( *((_QWORD *)&xmmword_14000B0F0 + 1) > 0xFui64 )
v13 = (__int64 *)qword_14000B0E0;
v14 = *((char *)v13 + v12) ^ 0x35; -> mã hóa chính
LODWORD(Block) = v14;
if ( v11 == (int *)v6 )
{
sub_140001C20(Buf1, v11, &Block);
v6 = v30;
v11 = (int *)Buf1[1];
}
else
{
*v11++ = v14;
Buf1[1] = v11;
}
++v9;
++v12;
v10 = xmmword_14000B0F0;
}
while ( v9 < (unsigned __int64)xmmword_14000B0F0 );
v8 = v7 + 232;
}
v15 = (char *)Buf1[0];
if ( v10 == 58 )
{
v16 = (char *)v11 - (char *)Buf1[0];
if ( v16 == v8 - v7 && !memcmp(Buf1[0], v7, v16) ) -> So sánh
{
v28[0] = (__int128)_mm_load_si128((const __m128i *)&xmmword_140007720);
v28[1] = (__int128)_mm_load_si128((const __m128i *)&xmmword_1400076B0);
v28[2] = (__int128)_mm_load_si128((const __m128i *)&xmmword_140007760);
v28[3] = (__int128)_mm_load_si128((const __m128i *)&xmmword_1400076F0);
v28[4] = (__int128)_mm_load_si128((const __m128i *)&xmmword_140007670);
v28[5] = (__int128)_mm_load_si128((const __m128i *)&xmmword_1400076A0);
v28[6] = (__int128)_mm_load_si128((const __m128i *)&xmmword_1400076E0);
v28[7] = (__int128)_mm_load_si128((const __m128i *)&xmmword_140007680);
v17 = (char *)operator new(0x80ui64);
Block = v17;
memmove(v17, v28, 0x80ui64);
do
{
sub_140001040("%c");
++v5;
v17 += 4;
}
while ( (unsigned __int64)v5 < 0x20 );
if ( Block )
j_j_free(Block);
}
}
v18 = 2i64 * v24;
v19 = *(_QWORD **)(*(_QWORD *)(a1 + 8) + 16i64 * v24);
v20 = (_QWORD *)*v19;
if ( (_QWORD *)*v19 != v19 )
{
do
{
v21 = *((int *)v20 + 4);
if ( !*(_BYTE *)(v21 + a3) )
sub_140004000(a1, v21, a3);
v20 = (_QWORD *)*v20;
}
while ( v20 != *(_QWORD **)(*(_QWORD *)(a1 + 8) + 8 * v18) );
}
if ( v7 )
j_j_free(v7);
if ( v15 )
{
v22 = v15;
if ( ((v6 - (_QWORD)v15) & 0xFFFFFFFFFFFFFFFCui64) >= 0x1000 )
{
v15 = (char *)*((_QWORD *)v15 - 1);
if ( (unsigned __int64)(v22 - v15 - 8) > 0x1F )
invalid_parameter_noinfo_noreturn();
}
j_j_free(v15);
}
}
```
- Nhìn khá dài dòng nhưng thực chất cách mã hóa chỉ đơn giản là xor với 0x35 và so sánh dữ liệu với biến có sẵn.
:bulb: Để lấy được bản rõ ta chỉ cần debug và trace đến biến Buf1 ở hàm memcmp() và bypass 2 hàm IsDebuggerPresent()
- Đặt breakpoint để bypass các hàm anti debug

*Đặt breakpoint ở vị trí đó và chỉnh Zflag=1 để bypass*
- Và nhập 58 kí tự a để đến được hàm memcmp()

- Sau khi debug đến được hàm memcmp() ta chỉ việc lấy giá trị của bản rõ sau đó xor với 0x35 là ra flag
Source code:
```
cp ="""
000000660000007C
000000610000007C
0000006100000071
0000004E00000060
0000005A00000076
000000520000005B
0000005400000047
0000004600000041
0000006C0000006A
000000400000005A
000000660000006A
000000590000005A
0000005000000043
0000006A00000051
0000007900000061
0000006A00000066
0000005400000076
0000005900000059
0000005400000057
0000005E00000056
000000670000006A
0000000500000050
0000006A00000004
000000540000007D
0000005000000043
000000730000006A
0000005B00000040
0000000F0000006A
000000480000001C
"""
result = []
cp = cp.replace("\n", "")
#kq
for i in range(0, len(cp), 16):
s = cp[i:i+16]
a1 = int(s[-2:], 16)
a2 = int(s[6:8], 16)
result.append(a1)
result.append(a2)
for i in result:
print(chr(i^0x35), end="")
```
### 3. Flag
ISITDTU{Congrats_You_Solved_TLS_Callback_Re01_Have_Fun_:)}
---
*Truongdz*