---
# System prepended metadata

title: '[WRITEUP ISITDTU 2024]'

---

# [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.
![image](https://hackmd.io/_uploads/SyLW5TNvyg.png)
- :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
![image](https://hackmd.io/_uploads/HkaZ3TNv1x.png)
*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.
![Screenshot 2025-01-15 125357](https://hackmd.io/_uploads/HkdKO0Evyg.png)
*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.
![Screenshot 2025-01-15 124704](https://hackmd.io/_uploads/Hy4FtC4Dye.png)
*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
![Screenshot 2025-01-15 134745](https://hackmd.io/_uploads/r1O-iREvyl.png)
*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
![Screenshot 2025-01-15 142210](https://hackmd.io/_uploads/ryMBmkSDyl.png)
*Đặt breakpoint ở vị trí đó và chỉnh Zflag=1 để bypass*
- Và nhập 58 kí tự a để đến được hàm memcmp()
![image](https://hackmd.io/_uploads/rJmOvySDyg.png)
- 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![Screenshot 2025-01-15 145315](https://hackmd.io/_uploads/SkHnqySP1l.png)
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*


