flat assembler
Message board for the users of flat assembler.
Index
> Windows > Running fasm Code in a Windows Kernel Mode Driver Goto page 1, 2 Next |
Author |
|
HyperVista 04 Jan 2007, 22:09
Sorry for the length of this post, but it takes some explaining...
While this approach won't help smoke (sorry, my fasm skills aren't good enough to help write a driver totally in fasm), this technique will enable running fasm code in a Windows kernel mode driver. This approach involves using the Microsoft tools to create the driver and linking in fasm produced .lib files into that driver. Microsoft and others in the Windows kernel development community insist that Windows drivers MUST be written with only the tools provided in the DDK (namely the MS assemblers ml.exe, etc.). I was advised numerous times to give up on trying to get fasm code compiled into the driver, but so far I haven't had any troubles, once I jumped through many M$ created hoops trying to get it to work. There is one issue I haven't worked out yet, and that's the SAFESEH issue. SAFESEH is a safe exception handling structure that is default on all the new MS linkers and is designed to prevent security issues such as buffer overflows. In order to get my fasm based drivers to compile and link, I have to turn off SAFESEH checking (the method for turning SAFESEH off in the linker is undocumented and it took me quite a while to figure it out). MASM has a .SAFESEH directive and I'd like to work on providing one in fasm. Perhaps some of you can help. Here goes: Tools you will need: fasm Windbg Windows DDK (Windbg and DDKs can be found here: http://www.microsoft.com/whdc/resources/downloads.mspx) VMWare or Virtual PC Beleive me, you'll want to test your drivers in a VM image, or on dedicated test machine because you will kill that test machine multiple times. VM images are easy and quick to re-do when you do hammer your machine. Configuring your tools: Windbg: After installing Windbg: 1) open the Symbol Search Path dialog (File -> Symbol File Path) 2) configure Windbg to use MS’s online Symbol Server and cache debug symbols locally: srv*c:\windows\symbols*http://msdl.microsoft.com/download/symbols 3) create a shortcut on your desktop to Windbg and specify the following command line: windbg –b –k com:pipe,port=\\.\pipe\com_1,resets=0 VMWare: 1) open the Configuration Editor from the Settings menu 2) Click the Add button to open the Add Hardware Wizard 3) Select Serial Port and click Next 4) Select Use Named Pipe, and change the name to: \\.\pipe\com_1 5) Select This end is the server 6) Select The other end is an application 7) Click on Advanced, and select Yield on CPU poll 8- Click Finish and then OK 9) When the VM boots (I use WinXP Pro) you need to edit the boot.ini file to read as follows: [boot loader] timeout=30 default-multi (0) disk (0) rdisk (0) partition (1) \WINDOWS [operating systems] multi (0) disk (0) rdisk (0) partition (1) \WINDOWS=”Microsoft Windows XP Professional” /fastdetect multi (0) disk (0) rdisk (0) partition (1) \WINDOWS=”Microsoft Windows XP Professional” – DEBUG /fastdetect /debugport=com1 /baudrate=115200 (note: the above options should be on one line and not wrapped around) Now, reboot the VMWare OS and while it’s booting, double click on the desktop shortcut to Windbg you created earlier to enter kernel mode debug. Setup the DDK Directory: 1) create a new folder in the WINDDK\3790.1830\src directory to hold your source files and other files need to build the driver 2) copy a makefile into this new folder (use any of the example makefile – don’t edit) 3) use notepad to create a “SOURCES” file (no extension) and place it in the new folder. an example SOURCES file is: TARGETNAME=<what you want to call the driver – no extension> TARGETPATH=.\lib TARGETTYPE=DRIVER TARGETLIBS=<your lib filename.lib> SOURCES=<list your source files (space separated)> NO_SAFESEH=1 Note: the NO_SAFESEH=1 statement is needed to get around the safe exception handling checking on your fasm generated .lib files that is now default on M$ linkers. If you don’t include this line the driver won’t build because of linker errors “unable to create safeseh image”. It took me a day to find this undocumented command (the alternative is to use MASM and the .SAFESEH directive to create a safe exception handler driver ….. no thanks!). It would be nice to have a SAFESEH capability for fasm so we don’t have to turn off” this safety feature to get our fasm based driver to compile….. Writing the Code: Driver code: I suggest starting with the source code for one of the sample drivers that comes with the DDK and plugging your code into that (call your fasm procs – be sure to declare your proc name as extern in the driver code). Use whatever editor you like but don’t compile the .c file. You need to use the DDK build utility to compile the source code (more on that later). Copy the .c file into the folder you created in the DDK directory earlier. Here's a brief sample driver: Code: #include "ntddk.h" #include "testdriver.h" #define NT_DEVICE_NAME L"\\Device\\hypervista" #define DOS_DEVICE_NAME L"\\DosDevices\\hypervista" extern myproc(); /* Function Declarations */ NTSTATUS hypervistaOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); NTSTATUS hypervistaClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); void hypervistaUnload(IN PDRIVER_OBJECT DriverObject); NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { PDEVICE_OBJECT deviceObject = NULL; NTSTATUS status; UNICODE_STRING NtNameString; UNICODE_STRING Win32NameString; KdPrint(("Hypervista driver entered!\n")); /* Create string version of the device name */ RtlInitUnicodeString(&NtNameString, NT_DEVICE_NAME); /* Create Device Object */ status = IoCreateDevice(DriverObject, 0, &NtNameString, FILE_DEVICE_UNKNOWN, 0, FALSE, &deviceObject); if (NT_SUCCESS(status)) { /* Create dispatch points for create/open, close, and unload */ DriverObject->MajorFunction[IRP_MJ_CREATE] = hypervistaOpen; DriverObject->MajorFunction[IRP_MJ_CLOSE] = hypervistaClose; DriverObject->DriverUnload = hypervistaUnload; KdPrint(("Hypervista driver just about ready!\n")); /* Create string version of the Win32 device name */ RtlInitUnicodeString(&Win32NameString, DOS_DEVICE_NAME); /* Create symbolic link between drive name and the Win32 namespace */ status = IoCreateSymbolicLink(&Win32NameString, &NtNameString); if(!NT_SUCCESS(status)) { KdPrint(("Hypervista driver couldn't create symbolic link\n")); IoDeleteDevice(DriverObject->DeviceObject); } else { KdPrint(("Hypervista driver initialized!\n")); } } else { KdPrint(("Hypervista drive couldn't create device.\n")); } return status; } NTSTATUS hypervistaOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { KdPrint(("Hypervista driver opened!\n")); KdPrint(("fasm Code is working!! %d\n", myproc())); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS hypervistaClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { KdPrint(("Hypervista driver closed!\n")); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } void hypervistaUnload(IN PDRIVER_OBJECT DriverObject) { UNICODE_STRING Win32NameString; KdPrint(("Hypervista driver Unloading.\n")); /* Create string version of our Win32 device name */ RtlInitUnicodeString(&Win32NameString, DOS_DEVICE_NAME); /* Delete the link from the device name to the Win32 namespace */ IoDeleteSymbolicLink(&Win32NameString); /* Delete device object */ IoDeleteDevice(DriverObject->DeviceObject); } Here's my simple test program to exercise the driver: Code: #include "windows.h" #include "stdio.h" HANDLE hTest; int main(int argc, char **argv) { hTest = CreateFile("\\\\.\\hypervista", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hTest != INVALID_HANDLE_VALUE) { printf("Hypervista Driver Working Properly!!\n"); CloseHandle(hTest); } else { printf("Can't get a handle to the Hypervista device....\n"); } return 0; } Here's my quick and dirty test fasm proc (note: I had to "mangle the name by adding the @0 to the end of the name because the MS compiler mangled the original). Thanks to Quantum for this test code! (I copied it from him on another thread) Code: format MS COFF public myproc as '_myproc@0' myproc: mov eax,5 ret fasm code: 1) use the MS COFF file format in fasm and declare your procedures as public (public myproc as ‘_myproc’) and compile to .obj file 2) use the DDK lib.exe utility to create a .lib file (located in the winddk\3790.1830\bin\x86 directory) lib /out:<what ever you want to call your filename.lib> <your filename.obj> 3) copy the resulting .lib file to the folder you created in the DDK directory earlier and add the .lib filename to the SOURCES file (TARGETLIBS=<.lib filename.lib> you created earlier. Compiling the Driver: 1) open the command line DDK and go to the folder/directory you created in winddk\3970.1830\src\ earlier. this folder should contain the following files: a. makefile b. SOURCES c. <your .lib file(s)> d. <your .c driver source file(s)> 2) type “build [-options]” Note: the options I like are: -cegZ (c=delete all object files, e=generate build log, g=display warnings in color, and Z=no dependency checking) (build –cegZ) Note: if you get link errors like “unresolved symbol” or “unresolved function”, check the build log (which was placed in your DDK folder). Check to see if it’s the proc you wrote in fasm only with some extra characters ….. name mangling!!!! Yes, name mangling, even though the driver is a .c file not .cpp …. thanks a lot Microsoft!!! You’ll have to go back into your fasm source file, change the name of the proc to match the mangled one as listed in the build log, recompile, re-create .lib file, copy it to DDK directory and run the DDK build utility again …. like I said,… thanks Microsoft … If all goes well, your driver will be built and placed into your DDK \<yourfoldername>\lib\i386 directory. Installing and Testing the Driver: 1) start your VMWare OS 2) copy your driver to the ..\windows\system32\drivers folder 3) edit the registry as follows (there are utilities out there, but I did mine manually): HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services Add a new node <your driver node name> Description = REG_SZ Starts the <your driver name> driver> DisplayName = REG_SZ <your driver name> ErrorControl = REG_DWORD 0x00000001 ImagePath = REG_EXPAND_SZ System32\Dirvers\<your dirvername.sys> Start = REG_DWORD 0x00000003 Type = REG_DWORD 0x00000001 4) restart the VMWare OS 5) start Windbg 6) go to Control Panel/Performance and Maintenance/System 7) click on the Hardware tab, click on the Device Manager button 8- click on View, and Show hidden devices 9) you will see a new device type show up the tree called Non-Plug and Play Drivers 10) expand that node and you should see your driver listed (if not, go back to regedit, change the Start = REG_DWORD value to 0x00000001, reboot, and repeat steps 5-8. 11) Right-click on your driver, click Properties, click the Driver tab, and click Start 12) check the Windbg window to see your driver start 13) Exercise your driver, checking Windbg for any KdPrint messages in your driver code. That's it. |
|||
04 Jan 2007, 22:09 |
|
sylwek32 05 Jan 2007, 00:36
wow hypervista. good work!
Thanks |
|||
05 Jan 2007, 00:36 |
|
MichaelH 05 Jan 2007, 01:55
Windows Kernel Mode Driver examples using fasm only -
Roki by okasvi http://board.flatassembler.net/topic.php?t=5812 KMD stuff by AMD64 http://board.flatassembler.net/topic.php?t=648 r0pc by L.chemist http://board.flatassembler.net/topic.php?t=3434 Of course jumping into kernel mode from user mode should be the preferred method for running kernel mode code..... well..., maybe not |
|||
05 Jan 2007, 01:55 |
|
MichaelH 05 Jan 2007, 03:37
Hi HyperVista
Quote:
We've just had the coldest winter ever recorded and I usually get into my shorts to cool down in October, here it is January and I'm still cold ..... Lucky this global warming thing is going to fix that Thanks for your efforts. |
|||
05 Jan 2007, 03:37 |
|
vid 05 Jan 2007, 06:11
HyperVista: post 2 very small driver examples, with and without SAFESEH, and we can reverse them to see what safeseh actually does.
some info here: http://msdn2.microsoft.com/en-us/library/9a89h429(VS.80).aspx maybe it is enough to define and export those structures, but it is also possible that there is some flag in header set, and tomasz would have to add it to formatter. |
|||
05 Jan 2007, 06:11 |
|
HyperVista 05 Jan 2007, 12:36
vid wrote:
Quote: post 2 very small driver examples, with and without SAFESEH, and we can reverse them to see what safeseh actually does will do. I found the link you provided during my search for "the answer". I think the link of interest for us from that page is the link to .SAFESEH (MASM directive) http://msdn2.microsoft.com/en-us/library/16aexws6(VS.80).aspx Here's some interesting text and code from that page: Code: Microsoft Macro Assembler Reference .SAFESEH to register a safe exception handler, create a new MASM file (as follows), assemble with /safeseh, and add it to the linked objects. .386 .model flat MyHandler proto .safeseh MyHandler end it will be interesting to learn exactly what the MASM directive .safeseh does |
|||
05 Jan 2007, 12:36 |
|
HyperVista 09 Feb 2007, 01:20
Update: here's a screen shot of kernel debugging via Windbg. it shows fasm code running in Windows XP device driver . fasm code checking to see if processor is Intel, checking to see if VMX (hardware virtualization) is supported, checking and setting CR4.VMXE[13], checking the lock bit MSR[0x3A] bit 0, and checking VMXON Enable MSR[0x3A] bit 2. Next step is to set-up VMCS (virtual machine control structure) and launching VMXON.
Last edited by HyperVista on 28 Aug 2007, 00:30; edited 2 times in total |
|||
09 Feb 2007, 01:20 |
|
vid 09 Feb 2007, 07:40
HyperVista: please assemble and send two short (preferably do-nothing) .obj files in MASM, one with SAFESEH and other without. i think we could find out enough info.
also, you can make SAFESEH for FASM procedures using MASM, as you mentioned, but i believe it's just matter of defining and exporting of structure, no big deal. PS: Can't wait till you show those engineers they weren't right. But my quess is that they are just lazy. |
|||
09 Feb 2007, 07:40 |
|
vid 13 Feb 2007, 08:59
got it!!! It's described in MS COFF specs:
Quote: 83The .sxdata Section unfortunately i don't know how to specify "IMAGE_SCN_LNK_INFO" on section with FASM, and what does "emit absolute symbol" mean. I think Tomasz's intervence would be handy here. |
|||
13 Feb 2007, 08:59 |
|
Tomasz Grysztar 13 Feb 2007, 11:23
You specify IMAGE_SCN_LNK_INFO in MS COFF format with "linkinfo" flag in section statement (usually you combine it with "linkremove" flag, I don't know if this is the case, too).
And emitting the absolute symbol may look like: Code: @feat.00 = 1 public @feat.00 |
|||
13 Feb 2007, 11:23 |
|
vid 13 Feb 2007, 11:37
tomasz: still, the flags 00300200h is set. Section flags should be just 00000200h. What are those two extra flags?
don: If you want to just get rid of linker complaining, add this to file: Code: @feat.00 = 1 public @feat.00 If you want to have some handler in assembly, you must also add '.sxdata' section, i will provide example soon. |
|||
13 Feb 2007, 11:37 |
|
Tomasz Grysztar 13 Feb 2007, 11:51
300000h is IMAGE_SCN_ALIGN_4BYTES, as default section alignment made by fasm is 4 bytes.
|
|||
13 Feb 2007, 11:51 |
|
HyperVista 13 Feb 2007, 19:41
Thank you vid and Tomasz. The @feat.# is exactly what I needed. I was able suppress the comiler errors by including "NO_SAFESEH=1" in the SOURCES file. That was a shortcut fix to the issue.
I set aside the SAFESEH issue to press forward with my fasm based hypervisor, concentrating instead on the VMX set-up and launch of VMXON. I thought I'd go back later and address the SAFESEH issue. With the information you provided on @feat.#, I can write a legitimate SAFESEH handler and .sxdata section in fasm. This is important because with without proper SAFESEH handlers the chances of getting the driver signed are slim. Thanks. |
|||
13 Feb 2007, 19:41 |
|
HyperVista 13 Feb 2007, 22:54
The DDK compiler didn't like the SAFESEH fix. One thing I think is curious is the error message, "error 'jvc' is not a recognized as an internal or external command" .... jvc???
My test fasm code is on the right. I appreciate the help, but nevermind the SAFESEH solution for now. I'll address that when I get the hypervisor launched. I've suppressed the SAFESEH error during build by including NO_SAFESEH=1 in my SOURCES file. With that shortcut fix, I can move forward. I really fix it later. Last edited by HyperVista on 14 Feb 2007, 01:35; edited 1 time in total |
|||
13 Feb 2007, 22:54 |
|
f0dder 13 Feb 2007, 23:25
HyperVista: a quick google for that error shows that the DDK build environment doesn't like paths with spaces in it
|
|||
13 Feb 2007, 23:25 |
|
HyperVista 14 Feb 2007, 01:33
Hi f0dder. Good to chat with you again. Thanks for the tip ... you are correct. When I underbarred the space between "Test" and "SAFESEH" those not so clear or helpful error messages disappeared. The DDK compilers are not very helpful.
It appears the addition of @feat.00 = 1 public @feat.00 doesn't stop the compiler from complaining about SAFESEH ... Thanks vid, Tomasz, and f0dder. I'll tackle the SAFESEH issue later. |
|||
14 Feb 2007, 01:33 |
|
vid 23 Feb 2007, 15:31
here are examples of minimal COFF with and without SAFESEH, compiled with MASM. Could someone find any difference besides "@feat.00"? Or can someone produce same COFF file as the one with SAFESEH is?
|
|||||||||||
23 Feb 2007, 15:31 |
|
vid 23 Feb 2007, 16:02
I see that this code in FASM:
Code: a=1 public a as "@feat.00" Tomasz: I think this would require new keyword or flag to be added... any ideas? |
|||
23 Feb 2007, 16:02 |
|
HyperVista 23 Feb 2007, 16:12
Quote: produces symbol of type C_EXT (public symbol) ". MASM produces "@feat.00" as C_STAT (private static symbol). This could be problem. yup! I think you are right vid. I'll test both .obj out tonight by linking them separately into my driver to see what happens with the SAFESEH compile warnings. I'm at my "real" job now and my fasm hypervisor dev machine is at home... I'll let you know. |
|||
23 Feb 2007, 16:12 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.