http://blog.csdn.net/hgy413/article/details/7107009
The following is only for 32-bit systems, tested under XP:
Here's how XP is called in Ring3:
[CPP]View Plaincopy
- Xp
- ntdll! Ntreadfile:
- 7c92d9b0 b8b7000000 mov eax,0b7h
- 7C92D9B5 ba0003fe7f mov edx,offset shareduserdata! SystemCallStub (7ffe0300)
- 7c92d9ba Ff12 call DWORD ptr [edx] ds:0023:7ffe0300={ntdll! Kifastsystemcall (7C92E4F0)}
- 7C92D9BC c22400 ret 24h
- 7C92D9BF-NOP
- ntdll! Kifastsystemcall:
- 7C92E4F0 8BD4 mov edx,esp
- 7C92E4F2 0f34 Sysenter
So the principle is also relatively simple, imitation can be, note SSDT to remove write protection!
Ring3:
[CPP]View Plaincopy
- #include "stdafx.h"
- #include <Windows.h>
- __declspec (naked) void Mykifastsystemcall ()
- {
- __asm
- {
- MOV edx,esp;
- __emit 0x0f;
- __emit 0x34;
- }
- };
- __declspec (naked) NTSTATUS Ntapi
- Iosystemcontrol (
- in ULONG Ioctrl,
- in PVOID inputbuf,
- in ULONG Inputbuflen,
- Out PVOID outputbuf,
- in ULONG Outputlen,
- Out Pulong Returnlen)
- {
- __asm
- {
- mov eax, 11Ch;
- Call Mykifastsystemcall
- RETN 0x18;
- }
- }
- int _tmain (int argc, _tchar* argv[])
- {
- char szbuf[100] = {0};
- ULONG outlen = 0;
- Iosystemcontrol (0x12345678,"hgy413", strlen ("hgy413"), Szbuf,99,&outlen);
- printf ("%s-%d\n", Szbuf, Outlen);
- GetChar ();
- return 0;
- }
RING0:
[CPP]View Plaincopy
- #include "Main.h"
- Def
- typedef struct _kservice_table_descriptor
- {
- Pulong Servicetablebase; //SSTD Base Address
- Pulong Count; //contains a counter for the number of invocations per service in SSDT. This counter is typically updated by Sysenter
- ULONG tablesize; //number of services described by Servicetablebase
- Puchar argumenttable; //contains the base address of each system service parameter byte table-system service parameter list each table entry is a uchar that represents a function parameter length
- } kservice_table_descriptor, *pkservice_table_descriptor;
- SSDT table has been exported, and here's the routine
- extern Pkservice_table_descriptor keservicedescriptortable;
- Kservice_table_descriptor ssdt_copy;
- ULONG newssdtservicetablebase[1024] = {0};
- UCHAR newssdtservicetablenumber[1024] = {0};
- NTSTATUS
- Iosystemcontrol ( in ULONG Controlcode,
- in PVOID inputbuffer OPTIONAL,
- in ULONG inputbufferlength,
- Out PVOID outputbuffer OPTIONAL,
- in ULONG outputbufferlength,
- Out pulong returnlength OPTIONAL
- )
- {
- NTSTATUS Status = status_success;
- if (Outputbuffer&&mmisaddressvalid (OutputBuffer))
- {
- Kdprint (("%s\r\n", InputBuffer));
- memset (OutputBuffer, 0x41, outputbufferlength); //Outgoing buf becomes AAAAA ...
- if (returnlength&& mmisaddressvalid (returnlength))
- {
- *returnlength = 10; //Outgoing size arbitrarily set to ten
- }
- }
- return Status;
- }
- void Ntosaddssdtservicetable (
- PVOID newfunction,
- ULONG Newnumber
- )
- {
- NTSTATUS Status = status_success;
- Peprocess Process;
- //Prohibit write protection, otherwise blue screen
- __asm
- {
- MOV EAX, CR0;
- OR EAX, 10000H;
- MOV CR0, EAX;
- STI;
- }
- //Copy original service table
- //Copy the original table to our array
- memcpy
- Newssdtservicetablebase,
- Keservicedescriptortable->servicetablebase,
- Keservicedescriptortable->tablesize * 4
- );
- //number of primitive functions
- memcpy
- Newssdtservicetablenumber,
- Keservicedescriptortable->argumenttable,
- Keservicedescriptortable->tablesize
- );
- //Modify SSDT Table Add service function
- Newssdtservicetablebase[ssdt_copy. Tablesize] = newfunction;
- Newssdtservicetablenumber[ssdt_copy. Tablesize] = Newnumber;
- //update memory inside Export keservicedescriptortable SSDT table
- Keservicedescriptortable->servicetablebase = Newssdtservicetablebase;
- keservicedescriptortable->argumenttable = Newssdtservicetablenumber;
- Keservicedescriptortable->tablesize = ssdt_copy. Tablesize + 1;
- //Resume write protection
- __asm
- {
- MOV EAX, CR0;
- OR EAX, 10000H;
- MOV CR0, EAX;
- STI;
- }
- }
- VOID ddkunload (in Pdriver_object pdriverobject)
- {
- Kdprint (("[ddkunload]-start\n"));
- //Restore the original
- Keservicedescriptortable->servicetablebase = ssdt_copy. Servicetablebase;
- Keservicedescriptortable->count = ssdt_copy. Count;
- Keservicedescriptortable->tablesize = ssdt_copy. Tablesize;
- keservicedescriptortable->argumenttable = ssdt_copy. argumenttable;
- Kdprint (("[ddkunload]-end\n"));
- }
- NTSTATUS DriverEntry (in Pdriver_object pdriverobject,
- In Punicode_string Pregistrypath)
- {
- Kdprint (("[driverentry]-start\n"));
- Pdriverobject->driverunload = Ddkunload;
- //Save the original
- Ssdt_copy. Servicetablebase = keservicedescriptortable->servicetablebase;
- Ssdt_copy. Count = keservicedescriptortable->count;
- Ssdt_copy. Tablesize = keservicedescriptortable->tablesize;
- Ssdt_copy. Argumenttable = keservicedescriptortable->argumenttable;
- //We call the Custom function to add memory to the SSDT table
- Ntosaddssdtservicetable (Iosystemcontrol, 24);
- Kdprint (("[driverentry]-end\n"));
- return status_success;
- }
After the driver is loaded, you can see:
To run the Ring3 applet, you can see that the outbuf is aaaaa., size 10:
ring0-new SSDT entry for communication (handy code)