---
# System prepended metadata

title: Anti-debug.Timing & assembly instruction (p3)
tags: [windows-internal, rev, anti-debug]

---

# Anti-debug.Timing & assembly instruction (p3)
Khi process được trace trong khi debug, thời gian delay giữa các câu lệnh rất lớn so với thời gian thực thi bình thương.
## 1. RDPMC/RDTSC
Là 2 câu lệnh sử dụng cờ PCE trong thanh ghi CR4.
>RDPMC chỉ được dùng trong Kernel mode
>RDTSC được sử dụng trong user mode. (IDA, x96dbg)

>NOTE: time counting bắt đầu count từ thời điểm gặp rdpmc
```cpp=
bool IsDebugged(DWORD64 qwNativeElapsed)
{
    ULARGE_INTEGER Start, End;
    __asm
    {
        xor  ecx, ecx
        rdpmc
        mov  Start.LowPart, eax
        mov  Start.HighPart, edx
    }
    // ... some work, functions...
    // Nếu debbuger step trace hoặc set breakpoint trong đoạn này -> large delay time -> debugger bẹhavior detected.
    __asm
    {
        xor  ecx, ecx
        rdpmc
        mov  End.LowPart, eax
        mov  End.HighPart, edx
    }
    return (End.QuadPart - Start.QuadPart) > qwNativeElapsed;
}
```

### detect
yara
```yaml=
strings:
    $rdtsc = { 0F 31 } 
    $rdpmc = { 0F 33 }
condition:
    uint16(0) == 0x5A4D and any of them
```

## 2. GetLocalTime, GetSystemTime
Tương tự như cách trên nhưng sử dụng Windows API GetLocalTime, GetSystemTime, GetTickCount, timeGetTime, QueryPerformanceCounter

```cpp=
SYSTEMTIME stStart, stEnd;
GetLocalTime(&stStart);
// ... some work functions...
// Nếu debbuger step trace hoặc set breakpoint trong đoạn này -> large delay time -> debugger bẹhavior detected.
GetLocalTime(&stEnd);
```

```cpp=
GetSystemTime(&stStart);
// your code.
GetSystemTime(&stEnd);
```

```cpp=
DWORD dwStart = GetTickCount();
// your code
return (GetTickCount() - dwStart) > dwNativeElapsed;
```

```cpp=
DWORD dwStart = timeGetTime();
// some work
return (timeGetTime() - dwStart) > dwNativeElapsed;
```

```cpp=
LARGE_INTEGER liStart, liEnd;
QueryPerformanceCounter(&liStart);
// your code
QueryPerformanceCounter(&liEnd);
return (liEnd.QuadPart - liStart.QuadPart) > qwNativeElapsed;
```

## 3. ZwGetTickCout/KiGetTickCount
Cả 2 hàm đều sử dụng từ [kernel mode](https://fragglet.github.io/dos-help-files/alang.hlp/x_at_L829d.html).

```cpp=
bool IsDebugged(DWORD64 qwNativeElapsed)
{
    ULARGE_INTEGER Start, End;
    __asm
    {
        int  2ah
        mov  Start.LowPart, eax
        mov  Start.HighPart, edx
    }
    // ... some work
    __asm
    {
        int  2ah
        mov  End.LowPart, eax
        mov  End.HighPart, edx
    }
    return (End.QuadPart - Start.QuadPart) > qwNativeElapsed;
}
```
### detect
yara
```yaml=
strings:
    $int_2a = { CD 2A } 
condition:
    uint16(0) == 0x5A4D and $int_2a
```

## bypass
patch các hàm check time = NOPs hoặc set lại giá trị trả về.

# Assembly instructions
## 1. INT 3
Là một interuption được sử dụng như một software breakpoint. Trong trường hợp không có debugger, câu lệnh này sẽ raise EXCEPTION_BREAKPOINT (0x80000003) exception và một exception handler sẽ được gọi.

Nếu có debugger, luồng điều khiển sẽ **không** được đưa tới exception handler để xử lí.
> 
```cpp=
__try{
    __asm int 3;
    return true;
}__except(EXCEPTION_EXECUTE_HANDLER){
    return false;
}
```

## 2. INT 2D
Tương tự như INT3, INT 2D cũng sẽ raise EXCEPTION_BREAKPOINT exception. 
> Nhưng với INT 2D, Windows sử dụng thanh ghi IP (instruction pointer) như một địa chỉ exception.Nếu EAX = 1, 3, 4; thanh gi IP sẽ tăng thêm 1.
> 
## 3. DebugBreak
raise breakpoint exception trên tiến trình hiện tại. Nếu không có debugger, luồng điểu khiển sẽ được xử lí bởi exception handler.
```cpp
__try{
    DebugBreak();
}
__except(EXCEPTION_BREAKPOINT){
    return false;
}

return true;
```
## 4. ICE
Its opcode is 0xF1, được dùng để phát hiện nếu chương trình bị traced.
## 5. Stack Segment Register
Cũng được dùng để phát hiện single-stepping
> Không có 64bit code version vì thanh ghi SS không được hỗ trợ.
```cpp
bool bTraced = false;
__asm{
    push ss
    pop ss
    pushf // push trap flag on stack
    test byte ptr [esp+1], 1 // examine the trap flag
    jz movss_not_being_debugged
}
bTraced = true;
movss_not_being_debugged:
    // restore stack
    __asm popf;
    return bTraced;
```
## 6. Instruction counting
Sử dụng debugger handle cho EXCEPTION_SINGLE_STEP exception.
Ta sẽ chèn các hardware breakpoint vào chuỗi code thực thi. Exception từ hardware breakpoint sẽ bị bắt bởi vectored exception handler, ta sẽ sử dụng biến đếm tăng lên 1 mỗi lần bắt được exception. khi chạy đến cuối chuỗi code thực thi, ta sẽ so sánh biến đếm để xác định có bị debug không. Nếu khác -> bị debug.

## 7. POPF và Trap Flag (TF)


| Bit | Mask | Abbreviation | category
| -------- | -------- | -------- | -------- |
| 8     | 0x0100  | TF     | Trap flag (single step) | control|

Trap Flag trong thanh ghi Flags, khi TF được set, sẽ raise SINGLE_STEP exception. Tuy nhiên, khi ta trace code, TF sẽ bị clear bởi debugger, nên sẽ không nhảy vào exception hander.

```cpp
__try{
    __asm{
        pushfd // push Flags register into stack
        mov dword ptr [esp], 0x100 // change stack value
        popfd // set TF
        nop
    }
    return true;
}__except(GetExceptionCode() == EXCEPTION_SINGE_STEP? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_EXCUTION)
    return false;
```
## 8. Instruction prefixes
Lợi dụng cách hoạt động của debugger khi gặp các lệnh prefixes.

Nếu thực thi cùng debugger, sau khi đến byte F3; Debugger skip prefix và nhảy tới câu lệnh INT1.

Nếu chạy mà không có debugger, exeption sẽ raise và luông thực thi sẽ vào exception handler.
```cpp
__try
{
    // 0xF3 0x64 disassembles as PREFIX REP:
    __asm __emit 0xF3
    __asm __emit 0x64
    // One byte INT 1
    __asm __emit 0xF1
    return true;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
    return false;
}
```
## bypass:
- Patch với lênh NOP.
## detect
yara
```yaml
strings:
    $int3 = { CC }
    $intCD = { CD }
    $int03 = { 03 }
    $int2D = { 2D }
    $ICE = { F1 }
    $Prefix = { F3 }
    $pushss_popss = { 16 17 }
    $pushf = { 9C }
condition:   
    uint16(0) == 0x5A4D and any of them
```

###### tags: `windows-internal` `anti-debug` `rev`