flat assembler
Message board for the users of flat assembler.

Index > Windows > Interrupt interception

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
Artlav



Joined: 23 Dec 2004
Posts: 188
Location: Moscow, Russia
Artlav 13 Sep 2007, 20:34
A three-line problem under DOS, no-idea-how problem under Windows:
How can a user mode program under WinNT/XP intercept an interrupt?

Details - the program loads some code into memory, runs it, and should react if the code calls int 80h.
I see 2 possibilities - intercepting interrupt ala DOS, or handling an exception arisen from it, getting the address, handling interrupt if address points to int 80h opcode, returning to after the opcode.
Static reconstruction of the code is not feasible.

Any ideas...?
Post 13 Sep 2007, 20:34
View user's profile Send private message Visit poster's website Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 13 Sep 2007, 22:47
no way... what is point in that? why can't you call what would be interrupt handler directly?
Post 13 Sep 2007, 22:47
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 13 Sep 2007, 23:08
Running Linux ELF executables under Windows?

I see that my WinXP SP2 produces an memory access violation telling that address $FFFFFFFF cannot be read. The problem however is how much you can rely on this. You can trap the exception and perform proper emulation but what if in a newer version of Windows this int starts to be used?

I see no user-mode possible way to achieve this but perhaps the DDK says something about registering ints so you can either make sure that the int will raise an exception or implement the service in the driver (with IPC with a user-mode service or directly in kernel-mode).
Post 13 Sep 2007, 23:08
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 13 Sep 2007, 23:49
Personally I doubt DDK will provide something like that, but it is possible.

Loco: you mean original ELF executables designed for running in linux? I think that is hard enough task to require ring0 code anyway...
Post 13 Sep 2007, 23:49
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 14 Sep 2007, 00:03
vid: Any example of something that mandatory needs ring0? Although I suppose that must be one, none comes to my mind Confused (as if I were imaginative)
Post 14 Sep 2007, 00:03
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 14 Sep 2007, 00:47
Executable layout? For example implementing "brk()" syscall using windows API could be quite big problem. Which call will you use to allocate image of executable, so that later it can be extended to huge sizes in case of brk()? I Think Heap*** won't handle that big block very well, VirtualAlloc won't allow you to enlarge block without moving it, dunno about Global/Local***.

Actually, i wouldn't be so concerned about interrupts that much. AFAIK 99.999% apps use dynamically linked glibc instead of syscalls.
Post 14 Sep 2007, 00:47
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 14 Sep 2007, 01:15
Can't you just call VirtualAlloc using as lpAddress param an address contiguous to the last allocated page? The 3G/1G layout is something that you can't resolve though (and I think that even in ring0 it will be problematic as the rest of the system works with a 2G/2G layout). However, if I remember right this layout is parametrizable in Linux kernels so Linux applications should not rely much in such layout.

About glibc, I was thinking about using native libraries as well so the kernel calls must exist somewhere. Something that must be assured is that binaries uses int $80 and not SYSENTER/SYSCALL instructions as some distros compiled to a specific arch can have. I know that exists a virtual shared library that is used for system calls but I don't know the implementation of it but I suppose the binary expects some patching on the kernel and/or dynamic linker side to use the proper CPU instruction (in which case it would be somewhat easy to perform emulation, I think).
Post 14 Sep 2007, 01:15
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 14 Sep 2007, 01:29
Quote:
Can't you just call VirtualAlloc using as lpAddress param an address contiguous to the last allocated page?

how exactly would you do that? does windows quarantee that all space inbetween is usable? if yes, then it probably could be done.

i hope you aren't thinking seriously about such utility Smile
Post 14 Sep 2007, 01:29
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 14 Sep 2007, 02:45
It is supposed that first 64 KB are unnusable because some functions considers those addresses as atoms. But, from 64KB to 2GB is user address space. If an obsticle appears when you try to expand memory you just return error condition as if there were no more memory.

About if I'm thinking seriously about this utility remember that I'm not the thread author Wink

Also note that such utility already exists but I never tried it and the main site is broken. Anyway, here is the download link (comes with sources).

PS: No, I recalled few minutes ago that this emulator was discussed on this forum so don't tell that I robbed the idea of an Int $80 driver from there Razz
Post 14 Sep 2007, 02:45
View user's profile Send private message Reply with quote
Artlav



Joined: 23 Dec 2004
Posts: 188
Location: Moscow, Russia
Artlav 14 Sep 2007, 03:28
Yes, iam trying to make a small-scale linux binary emulator.

Loading and dynamically linking ELF's to the libc analog is not a problem, so all kind of "hello world" and example programs works, but when i tried some of the real ones, most crashes on int 80h instruction, so i considered the syscalls.

How is it done in virtualisation software? Some kind of static analysis, exception handling, driver or something else?

Thank you for LINE link, looks interesting.
Is there anything alive/under development on that topic?
Post 14 Sep 2007, 03:28
View user's profile Send private message Visit poster's website Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 14 Sep 2007, 07:53
Quote:
How is it done in virtualisation software?

Driver, with LOTS of trickery.

I think you could go the way with catching that memory access exceptions, and check if they are caused by "int 80" (CD 80).

Also mind differences between MS libc and glibc, you may rather want to use Mingw glibc for win32 (if there is something like that)
Post 14 Sep 2007, 07:53
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
Feryno



Joined: 23 Mar 2005
Posts: 509
Location: Czech republic, Slovak republic
Feryno 14 Sep 2007, 12:50
hi, currently I'm fighting with the same problem by developping driver for fdbg
something finished to work, something no, the biggest problem - I don't have multi CPU system to test it
only bare copy & paste from my problems.howto, you must extract thoughts usefull for you
I'll be out for 1 week holidays, don't expect anything more from me until my return back from holidays
but don't surrend, your problem really has solution

hooking interrupts

problem No.1
LastBranchFromIP, LastBranchToIP, LastExceptionFromIP, LastExceptionToIP are read-only registers. They can be easily read during task switching, but they CAN'T BE WRITTEN back as threads switch. Microsoft reserved space for all 4 registers in ThreadContext structure, but the space is wasted because it can't be used!
solution: We hook exception interrupts and store these registers at the earliest beginning of exception handler

problem No.2
Multicore CPUs are common todays. We need to load interrupt descriptor table at every CPU in the system.
solution: We won't create new IDTR neither load it using LIDT [IDTR]. We just hook some interrupt vectors which resides in memory. Memory is supposed to be the same for all CPUs in the system as well IDTR is supposed to be the same for every CPU.
-> But:
If the operating system detects an application or driver that patches the kernel, it generates a bug check and shuts down the system. Modifications that trigger this behavior are:
- Modifying system service tables.
- Modifying the interrupt descriptor table (IDT).
- Modifying the global descriptor table (GDT).
- Using kernel stacks that are not allocated by the kernel.
- Patching any part of the kernel (detected only on AMD64-based systems).
Over time, patch protection will be extended to protect additional kernel resources.
successfully run in my Vista x64 without any problem...

problem No.3
LastBranchFromIP, LastBranchToIP, LastExceptionFromIP, LastExceptionToIP registers are specific for only one CPU, they certainly differs in other CPUs in multi-CPU systems.
solution: No matter which CPU holds what addresses of these registers... The only one CPU causing the exception saves these 4 registers at the begin of exception handler which is the same for all CPUs as described in the solution for problem No.2.

problem No.4
The most valuable exception is Page-Fault (int0E). Unfortunatelly, this exception is heavily used by operating system itself for loading pages from swap drive. OS changes all 4 registers with branches very rapidly when loading pages from swap.
solution: Disabling swapping memory. Should work fine. But who want to do it in this way?
second solution: Yes. It exist. Handling int0E requires taking care of the privilege level of the thread causing exception. If the privilege level is the highest, it is allmost OS Page-Fault loading pages from swap (or fatal error in kernel or driver). If the privilege level is the lowest, it is allmost our user-mode program being debugged (or another program running in user-mode). We can access privilege level in rflags register whis is pused into stack by CPU itself just before CPU changes control of execution from program to exception handled.

problem No.5
enabling branches recording requires to enable it in every CPU in multicore CPUs system
solution: enable control register in every CPU KeGetCurrentProcessorNumber, then for every CPU PsCreateSystemThread set thread affinity mask ZwSetInformationThread

edit from 20100201 deleted the attachment because reached the quota limit, download a sample of working driver from download page of flat assembler


Last edited by Feryno on 01 Feb 2010, 14:08; edited 1 time in total
Post 14 Sep 2007, 12:50
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 14 Sep 2007, 14:31
This is the Int $80 handler that LINE uses
Code:
;
; $Id: handler.asm,v 1.2 2001/05/01 17:39:00 mvines Exp $
;
; Copyright (C) 2001  Michael Vines
;
.386
.model small

.data
    _syscallHandlerPtr dd 0

.code

public _InterruptHandler

_InterruptHandler proc

    ; Check for SYSCALL_LINEXEC_HANDLER
    CMP     EAX, 0DEADBEEFh
    JNE     reflect_syscall

    MOV     DS:_syscallHandlerPtr, EBX
    IRETD


reflect_syscall:
    PUSH    EAX

    ; simple sanity check
    MOV     EAX, DS:_syscallHandlerPtr
    CMP     EAX, 0
    JE      no_handler

    PUSH    EBX

    MOV     EBX, DWORD PTR [ESP+8]  ; read userland EIP from stack
    MOV     DWORD PTR [ESP+8], EAX  ; set EIP to syscall handler 

    MOV     EAX, DWORD PTR [ESP+8+12]  ; get ESP from stack
    SUB     EAX, 4
    MOV     DWORD PTR [ESP+8+12], EAX  ; write new ESP 
    MOV     DWORD PTR [EAX], EBX         ; place EIP on top of userland stack

    POP     EBX
    
    JMP     exit_handler

no_handler:
    POP     EAX
    PUSH    -38                         ; -38 == ENOSYS

exit_handler:
    POP     EAX
    IRETD

_InterruptHandler endp

End    


Not sure if the handling occurs in user-mode though. Take a look on the sources to get an idea. The project seems to be abandoned because the last update is from May 29, 2001 (where he added the driver so, he was using the exception handling approach before?).

I think that running native linux binaries is possible and implementing the syscalls is of moderate difficulty, the problem is simulating the environment, I think that emulating the entire filesystem would be a pain (and I bet LINE does few or nothing at emulating /proc, /dev, etc).
Post 14 Sep 2007, 14:31
View user's profile Send private message Reply with quote
Artlav



Joined: 23 Dec 2004
Posts: 188
Location: Moscow, Russia
Artlav 14 Sep 2007, 14:47
vid wrote:
Driver, with LOTS of trickery.
I think you could go the way with catching that memory access exceptions, and check if they are caused by "int 80" (CD 80).
Driver. Tryed that, made a typo, curiously stared at BSOD for a couple of seconds, decided to put it off as last measure.

Problem was relatively solved by using VectoredExceptionHandler, handler checks for instruction at error address, if it's an int 80h then do the syscall.
Works fine for read/write and exit like ones, but i already expect problems with something like fork.
vid wrote:
Also mind differences between MS libc and glibc, you may rather want to use Mingw glibc for win32 (if there is something like that)
I do compile it with Mingw, and for now just wrapping the functions work fine... Scale is the question.
Feryno wrote:
hi, currently I'm fighting with the same problem by developping driver for fdbg
something finished to work, something no, the biggest problem - I don't have multi CPU system to test it
only bare copy & paste from my problems.howto, you must extract thoughts usefull for you
I'll be out for 1 week holidays, don't expect anything more from me until my return back from holidays
but don't surrend, your problem really has solution

Thank you for the code, though it's usability is questionable, since i only consider win32.
Post 14 Sep 2007, 14:47
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 14 Sep 2007, 17:54
http://colinux.org/ <- Another project that is not dead Smile
Post 14 Sep 2007, 17:54
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1903
DOS386 14 Sep 2007, 21:27
> A three-line problem under DOS

Valid for RM INT's only Wink

> no-idea-how problem under Windows

Very big Crying or Very sad

> How can a user mode program under WinNT/XP intercept an
interrupt?

Probably via Ring0 only Wink

> see 2 possibilities - intercepting interrupt ala DOS

This won't work on XP/Vi$ta Laughing

If you want to explore Ring0, simplest code
I've seen so far:

http://board.flatassembler.net/download.php?id=3251

PS: Posted with Arachne DOS browser.
FASM forum (like most other forums) doesn't look
best here but it's usable Smile

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 14 Sep 2007, 21:27
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 14 Sep 2007, 21:41
Isn't simplier to just write a driver than relaying on a hacky ring3 program that accesses the physical memory device? LINE sources includes the required driver anyway so he can borrow it from there.
Post 14 Sep 2007, 21:41
View user's profile Send private message Reply with quote
xspeed



Joined: 16 Aug 2007
Posts: 22
xspeed 15 Sep 2007, 15:43
most windows api used kifast and used sysenter
Post 15 Sep 2007, 15:43
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 16 Sep 2007, 17:14
Writing a driver is the best way and easiest way to do things, imho you shouldn't rely on the physmem access hack... hopefully it's going to be patched on future windows systems.
Post 16 Sep 2007, 17:14
View user's profile Send private message Visit poster's website Reply with quote
xspeed



Joined: 16 Aug 2007
Posts: 22
xspeed 16 Sep 2007, 19:55
who in here have the source code to windows 2000 or wndows xp?
Post 16 Sep 2007, 19:55
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.