Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ERROR: UMD EXEC: Could not get IAT Info #8

Open
Ac1dNe9n opened this issue May 8, 2023 · 40 comments
Open

ERROR: UMD EXEC: Could not get IAT Info #8

Ac1dNe9n opened this issue May 8, 2023 · 40 comments

Comments

@Ac1dNe9n
Copy link

Ac1dNe9n commented May 8, 2023

Hi.
After building everything in need. I try to insert rootkit to windows 10.But i get this error ERROR: UMD EXEC: Could not get IAT Info
After tring to figure out what's wrong using serial.It seems that the while loop in the 1243 line of function ProcessGetThunkInfoIAT in WinTools.c all goes to the continue and return False.How can i figure out what's wrong.Is there any way to debug this except printing infomation to serial.

== Initializing windows context struct ==
  Cleaning up old Windows struct ...
  Dynamic memory allocated before WinCtx init: 24
  PML4: 0x1ad000 Kernel entrypoint: 0x7fbb1889bd0
  Trying to find Ntos kernel ... 
  Kernel found!
  NT kernel: 0x7fbb1800000
  Parsing Windows kernel exports ...
  Parsing export table for 64-bit module ...
  Finished Export Table.. NameAmount 2916
  Dynamically allocating table ...
  Filling the export list ...
  Export list successfully filled!
  PsInitialSystemProcess: 0x7fbb128bc60
  SystemProcess: 0x7ef144d6cfc0
  NtVer: 1000
  NtBuild 18363
== Windows offsets set! ==

==  Finding target process ... ==

==  Found and dumped process! Starting IAT Hooking ==
  Getting process IAT Thunk ...
  Allocating 196608 bytes of memory for the PE image ...
ERROR: UMD EXEC: Could not get IAT Info!

By the way. I didn't find the code of switching to the LONG mode like Longkit you mentioned in your blog. Just found some defination of asm code deal with CR3 and CR4 without call them. Could you give me some indication about that.

@jussihi
Copy link
Owner

jussihi commented May 8, 2023

Hi @Ac1d-0-0 ,

thank you for your interest in the rootkit. First, EDK2 actually handles the switching to long mode. Otherwise there would not be 64-bit memory access to even start with.

Second, I'm sorry but during developing I've found no better way to output data from the system than actually printing out debug log via serial port. If you have a better solution, please let me know and I'll see if it could be added to the project.

Now, to your problem. Which program are you using as the target process for the rootkit? If you are using the sample program form this repo (smm_target), are you compiling it as a 64-bit binary and debugging symbols enabled? If the debugging is disabled, the rootkit was having some issues finding a codecave for the shellcode injected by SMM part of the rootkit.

@Ac1dNe9n
Copy link
Author

Ac1dNe9n commented May 8, 2023

Thanks for reply!
I compiled the x64 smm_target.exe with debugging symbols. actually i succeeded once and it created the hello smm file.Checking the serial output it still get lots of Couldn't get IAT Info before succeed.but after editing the code to try the create a process. it got this error. Now ,even i create a new win10 vm environment with the ovmf that i didn't modify still get this error message.
Another question is about triggering the SMI. It seems the system is triggering the SMI that you wrote automatically.
I used to write poc using chipsec to trigger the specific smi before . So I didn't figure out how does this work.It would be nice if you could explain that for me.

@Ac1dNe9n
Copy link
Author

Ac1dNe9n commented May 9, 2023

Rebuild the smm_target using vs 2019 solve the problem. Maybe the problem is caused by vs 2023.Thanks for your patient reply.

@Ac1dNe9n Ac1dNe9n closed this as completed May 9, 2023
@jussihi
Copy link
Owner

jussihi commented May 9, 2023

Rebuild the smm_target using vs 2019 solve the problem. Maybe the problem is caused by vs 2023.Thanks for your patient reply.

@Ac1d-0-0 Sorry for taking long to answer, I was sleeping :-) But interesting find! If you have time to research the root cause, it would surely be nice add to the rootkit, since it seems like the IAT hooking method used is a bit dated (if it doesn't work with executables compiled by newer MSVC).

Since the IAT hooking and most of the WinTools is copied from Ulf Frisk's memprocfs/pcileech, you could check what has changed in his IAT hooking implementation: memprocfs's vmmwin.c. This corresponds to my function ProcessGetThunkInfoIAT, which you pointed out in your original issue text.

But if you don't have the time, I don't blame you. However, I want to remind that the repo is licensed under GPL3. I.e., if you make improvements/changes, please make them publicly available.

@jussihi
Copy link
Owner

jussihi commented May 9, 2023

Another question is about triggering the SMI. It seems the system is triggering the SMI that you wrote automatically. I used to write poc using chipsec to trigger the specific smi before . So I didn't figure out how does this work.It would be nice if you could explain that for me.

@Ac1d-0-0 , ah, there was also this question.

This rootkit registers itself as the "root SMI handler" which means that any SMI generated should first execute our SMM rootkit's code, then forward to the real designated SMI handler. It is kind of "hooking" any incoming SMI to first execute our code.

SMI generation: There are multiple ways to trigger SMIs. One way is to generate them programmatically. And you are right, the system generates them automatically. You can also generate them periodically if you have Intel CPU. See "Periodic SMI" slide on https://opensecuritytraining.info/IntroBIOS_files/Day1_07_Advanced%20x86%20-%20BIOS%20and%20SMM%20Internals%20-%20SMM.pdf

@Ac1dNe9n
Copy link
Author

Ac1dNe9n commented May 9, 2023

Bad news is that i still get the ERROR: UMD EXEC: Could not get IAT Info after three(maybe four) times rebooting the vm. It turned out that the success exec today may just be a coincidence. I'm still trying to debugging and reviewing to find the problem.
Thanks for the answer! It helps a lot.

@jussihi
Copy link
Owner

jussihi commented May 9, 2023

Bad news is that i still get the ERROR: UMD EXEC: Could not get IAT Info after three(maybe four) times rebooting the vm. It turned out that the success exec today may just be a coincidence. I'm still trying to debugging and reviewing to find the problem. Thanks for the answer! It helps a lot.

You can reopen this issue if it persists.

Did your VM windows version update after these reboots? What is the current build version from Windows version info?

@Ac1dNe9n
Copy link
Author

Ac1dNe9n commented May 9, 2023

It's still 1909. I disable the windows update after install.And i also made a clone of the vm before using the UEFI rookit.

@Ac1dNe9n Ac1dNe9n reopened this May 9, 2023
@jussihi
Copy link
Owner

jussihi commented May 9, 2023

It's still 1909. I disable the windows update after install.And i also made a clone of the vm before using the UEFI rookit.

how about the kernel version? did it change? sounds very weird to me that it stops working after some time!

@Ac1dNe9n
Copy link
Author

Ac1dNe9n commented May 9, 2023

It seems not the kernel version problem.Because replace the clone didn't fix.
I use serial to print the pIID[0].FirstThunk and it turn out to be 0 when i cannot get IAT Info.

1

But when i'm trying to add more serial output to figure out what's wrong.It suddenly miraculously obtained IAT and stuck at stage three here.The SMI didn't give back the control to the windows so windows also stucked.
2
After commenting the code before. Everything work smoothly and get what the Hello SMM. ( Weird day - -)
I will keep debugging to figure out what's wrong. It would be even better if you could provide some suggestions.

@jussihi
Copy link
Owner

jussihi commented May 17, 2023

@Ac1d-0-0
ah, the "clean up" stage of the UMD IAT hooking/injection does something that freezes the PC. And yes, commenting that part out leaves the written code & data to code cave and data caves, but that way it at least works :-)

Have you found out anything regarding the other problems? Even if not, let's keep this issue open for the time being - if someone else tries out the rootkit they will very likely face the same issue! So thanks for reporting.

By the way, what operating system are you running in your host system? Ubuntu?

@Ac1dNe9n
Copy link
Author

Ac1dNe9n commented May 17, 2023

I use Windows 11 as my host system and WSL Ubuntu to run a libvirt and start the qemu.
After I commented that part of the code the previous problem never occurred again (at least so far).But that part of the code does not theoretically affect the previous part.
I have some other thing recently in doing these days so i temporarily did not continue to debug. I will reply to you in the issue if I find something in the follow-up debugging.

@Ac1dNe9n
Copy link
Author

I seems figuring out what's the problem.
Your code copy the page of the target exe to your malloc address. Then try to loop the ImportDirectory. But it turned out that in my environment. The NameRVA and FirstThunk in struct PIMAGE_IMPORT_DESCRIPTOR is zero in memory. So it get out of the loop and print Cound not get IAT info.
image
I speculate that the cause of the problem is the issue of Windows memory paging.That part of data is not real in the physical memory at that time.Maybe it's swapped out. And that may be the reason why sometime the code can run and sometime not. But i still cannot figure out how to solve this problem yet.
Do you have any suggestion? Thanks

@jussihi
Copy link
Owner

jussihi commented Jun 12, 2023

I seems figuring out what's the problem. Your code copy the page of the target exe to your malloc address. Then try to loop the ImportDirectory. But it turned out that in my environment. The NameRVA and FirstThunk in struct PIMAGE_IMPORT_DESCRIPTOR is zero in memory. So it get out of the loop and print Cound not get IAT info. image I speculate that the cause of the problem is the issue of Windows memory paging.That part of data is not real in the physical memory at that time.Maybe it's swapped out. And that may be the reason why sometime the code can run and sometime not. But i still cannot figure out how to solve this problem yet. Do you have any suggestion? Thanks

@Ac1d-0-0 very interesting find! I cannot believe that the page(s) are swapped out... However, it can be checked! So, could you please check it via disabling swapping on Windows? I found this link: https://answers.microsoft.com/en-us/windows/forum/all/is-it-possible-to-disable-swapfilesys-to-minimize/ea0fe5dc-ad5c-4cf2-ab28-6a53ef964729 .

The first suspect to me was the v_memReadMultiPage function which I wrote to read memory areas that span across multiple pages (since their physical mapping can be fragmented even if the virtual addresses would be continuous). But that function seems to look good to my eye right now. If you can spot a problem in there, please feel free to fix it :-)

The second idea I got now is that maybe the target process is only partially initialized when SMM rootkit runs and fails (IAT imports are not initialized yet but the memory for them is allocated, or then the memory is not allocated and we are just reading some garbage data since the whole PIMAGE_IMPORT_DESCRIPTOR is uninitialized). Maybe we should try to restart the injection process (i.e. clean up and reset the static state variable WinUmdIATState currState to NO_PROCESS inside WinUmdIATHook.c's state machine) if the injection fails at this IAT step. Could you test this also? I can also do it myself but it'll take some time :) But if you are willing to contribute some time to this, please do test these ideas.

@Ac1dNe9n
Copy link
Author

Ac1dNe9n commented Jun 12, 2023

I disabled the swap and checked the serial output. It still not working.(seems not the swap problem)
The second idea was already done in your WindowsUmdIATHook actually.The code will return false and change the currState to NO_PROCESS.The next time it trigger the smi will allocate new pages and init.
I change the code to find the process explorer.exe. And i use CheatEngine to check the process virtual memory value in that structure.It looks right to me.But the Code still get zero in NameRVA
So it may be thev_memReadMultiPage 's problem or elsewhere.

image

@jussihi
Copy link
Owner

jussihi commented Jun 12, 2023

@Ac1d-0-0
yes, I also thought it could not be page swapping.

The code will return false and change the currState to NO_PROCESS.

Hmmm, ok, does it retry and fail again?

So it may be the v_memReadMultiPage 's problem or elsewhere.

Next thing I would do would be to log the physical page addresses from the v_memReadMultiPage to serial output. See if it works when physical pages are in continuous space but fail when they are fragmented..? i.e. 2 pages in virtual memory are after each other (4096 bytes between them) but in physical memory they reside separated from each other. This will cause a lot of log output but maybe it would show us if there is a bug in v_memReadMultiPage after all...

@Ac1dNe9n
Copy link
Author

Ac1dNe9n commented Jun 13, 2023

It seems the problem is the VTOP in the v_memReadMultiPage.
Some of the virtual address convert to physical address result is zero. which lead to the return false in the v_memReadMultiPage.So it just copy part of the process memory to the dest.
After adding some code to prevent v_memReadMultiPage return if pSrc is zero.The target IAT is found successfully.(Although the VTOP problem was not solved.The v_memReadMultiPage had copied enough memory to find the target IAT.)
image

I am thinking why not directly calculate the required virtual address through virtual address and offset, and then use VTOP to obtain the actual address before processing, so there should be no need for memory replication?

@jussihi
Copy link
Owner

jussihi commented Jun 13, 2023

It seems the problem is the VTOP in the v_memReadMultiPage. Some of the virtual address convert to physical address result is zero. which lead to the return false in the v_memReadMultiPage.So it just copy part of the process memory to the dest. After adding some code to prevent v_memReadMultiPage return if pSrc is zero.The target IAT is found successfully.(Although the VTOP problem was not solved.The v_memReadMultiPage had copied enough memory to find the target IAT.)

Great find! So just bypassing the return value from VTOP worked? This obviously needs to be fixed...

I am thinking why not directly calculate the required virtual address through virtual address and offset, and then use VTOP to obtain the actual address before processing, so there should be no need for memory replication?

Hmm, what do you mean by this? I would believe that this is just what we are doing in v_memReadMultiPage- We take the beginning virtual address - then find the physical memory page it is mapped to. After this we go through the virtual addresses page by page and find the physical memory mapped for each page. How would you optimize this? I mean, we need to call VTOP for every virtual memory page AFAIK.

But great that you found the root cause for this issue - let's find a fix for it. It might be that VTOP (virtual to physical) implementation is not bulletproof and that's why it's failing.

@jussihi
Copy link
Owner

jussihi commented Jun 13, 2023

I just had a short conversation with @pRain1337 about this issue. He pointed out that the problem might be VTOP's call to p_memCpy which checks whether the memory address you are copying is safe to access (by using IsAddressValid). It is a mystery why this check fails, since usually this kind of failure only happens very early during the boot procedure when Windows memory management is not completely initialized yet.

@Ac1dNe9n
Copy link
Author

But if its p_memCpy's fault and check fails. [p_memCpy] Aborted duo to disallowed memory range will be print to the serial. But i didn't get that

@jussihi
Copy link
Owner

jussihi commented Jun 13, 2023

@Ac1d-0-0

Ah, you are correct. So it must be something else failing then. Could you please check which if branch of the VTOP returns 0 in this case?

@jussihi
Copy link
Owner

jussihi commented Jun 13, 2023

image

@Ac1d-0-0 could you please also check here some of failing physical addresses (here 0x1aa7c46d8 for example) inside windows by using cheatengine/rweverything. Do they exist when you check via Windows? Or are they NULL there as well?

@Ac1dNe9n
Copy link
Author

Ac1dNe9n commented Jun 14, 2023

According to the screenshot.It return at the final if (!address).

I check some of the failing physical address.It's indeed zero in that physical memory.And i also use windbg's VTOP cmd to convert the virtual memory to physical memory.It get the same result and say zero PTE. Interesting found is that some of the failing physical address will be filled with the right value after some time.
image
image

@jussihi
Copy link
Owner

jussihi commented Jun 14, 2023

According to the screenshot.It return at the final if (!address).

I check some of the failing physical address.It's indeed zero in that physical memory.And i also use windbg's VTOP cmd to convert the virtual memory to physical memory.It get the same result and say zero PTE. Interesting found is that some of the failing physical address will be filled with the right value after some time. image image

Hm, so it seems like the SMM code is indeed correct. We just need to modify it so that with pages mapped to "0" mem address or that fail the p_memcpy operation (also resulting physical address 0 / NULL) due to invalid address, the v_memReadMultiPage should then just somehow report the missing pages to the caller function. Maybe this could be done by creating a bitmap of pages that were read successfully. This way we could just skip the invalid areas and continue with execution by jumping over these invalid areas in the caller function.

It seems like the behaviour you are witnessing is just Windows saving some RAM. Maybe your VM is configured for such low RAM that Windows thinks it's better to save some space by not loading the whole program to the memory at once. In system context (NTOS / kernel) this generates a page fault when the program tries to access these areas (and therefore you can also see some of the memory getting valid addresses "on demand" if you wait a bit) and the kernel then loads the required part from disk to memory and populates the PTE. But naturally we cannot do this from SMM. I think that's the problem. https://en.wikipedia.org/wiki/Page_fault

@Ac1dNe9n
Copy link
Author

Ac1dNe9n commented Jun 14, 2023

Ah,that's what I meant when I said the memory was swapped out earlier. Maybe the 8G of memory I allocated to the VM was not really enough. I'm currently skipping those invalid virtual addresses directly which does solve the problem.

I also find the reason why i cannot find code cave when i hook explorer.exe. The VTOP return zero in the code below.(Really a tricky problem)

    if (!vaCodeCave && (pSections[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) && ((pSections[i].Misc.VirtualSize & 0xfff) < (0x1000 - 0x100)))
    {
      vaCodeCave = TargetModule.baseAddress + ((pSections[i].VirtualAddress + pSections[i].Misc.VirtualSize + 0xfff) & ~0xfff) - 0x100;
      if (!VTOP(vaCodeCave & ~0xfff, TargetProcess.dirBase, TRUE))
      {
        SerialPrintString("read test failed!");
        vaCodeCave = 0; // read test failed!
      }
    }

image

By the way. I also tried my real PC. I simply replaced the SMM driver and the PiSmmCpuDxeSmm(a bit lazy). But i got the exception below when the code clean up the old windows struct and lead to the cpu deadloop.It seems some driver is still preventing me from accessing the memory outside the SRAM. Is there something that i miss?

== Initializing windows context struct ==
  Cleaning up old Windows struct ...
!!!! X64 Exception Type - 0D(#GP - General Protection)  CPU Apic ID - 00000000 !!!!
ExceptionData - 0000000000000000
RIP  - 000000007AAB9F7D, CS  - 0000000000000038, RFLAGS - 0000000000010046
RAX  - 0000000000000000, RCX - 0000000000000000, RDX - 00000000000003F8
RBX  - 0000000000000001, RSP - 000000007ADB7C50, RBP - 0000000000000000
RSI  - 00000000000003FD, RDI - 00000000000003F8
R8   - 0000000000000070, R9  - 0000000000000000, R10 - 0000000000000034
R11  - 000000007ADB7CC0, R12 - 6F14465E14CAB1E3, R13 - 0000000015CAB0E3
R14  - 00000000FFFFFF01, R15 - 000000007AFFB548
DS   - 0000000000000020, ES  - 0000000000000020, FS  - 0000000000000020
GS   - 0000000000000020, SS  - 0000000000000020
CR0  - 0000000080010033, CR2 - 0000000000000000, CR3 - 000000007AD8B000
CR4  - 0000000000000668, CR8 - 0000000000000000
DR0  - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
DR3  - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
GDTR - 000000007AD8A000 000000000000004F, LDTR - 0000000000000000
IDTR - 000000007AD95000 00000000000001FF,   TR - 0000000000000040
FXSAVE_STATE - 000000007ADB78B0
!!!! Can't find image information. !!!!

Thanks again for your patient reply!(Just started to learn these aspects so lots of questions to ask. 😆 ). Your project is really helpful to learn the whole process of making a SMM rootkit.

@jussihi
Copy link
Owner

jussihi commented Jun 14, 2023

Ah,that's what I meant when I said the memory was swapped out earlier. Maybe the 8G of memory I allocated to the VM was not really enough. I'm currently skipping those invalid virtual addresses directly which does solve the problem.

I also find the reason why i cannot find code cave when i hook explorer.exe. The VTOP return zero in the code below.(Really a tricky problem)

    if (!vaCodeCave && (pSections[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) && ((pSections[i].Misc.VirtualSize & 0xfff) < (0x1000 - 0x100)))
    {
      vaCodeCave = TargetModule.baseAddress + ((pSections[i].VirtualAddress + pSections[i].Misc.VirtualSize + 0xfff) & ~0xfff) - 0x100;
      if (!VTOP(vaCodeCave & ~0xfff, TargetProcess.dirBase, TRUE))
      {
        SerialPrintString("read test failed!");
        vaCodeCave = 0; // read test failed!
      }
    }

Hmm, 8 GB sounds enough to my ears but well, Windows does Windows things. However, if you can come up with a code patch fixing this issue, please contribute it (clone the repo and create a pull request) and let's find a good way to make it working but not too broken at the same time :-)

By the way. I also tried my real PC. I simply replaced the SMM driver and the PiSmmCpuDxeSmm(a bit lazy). But i got the exception below when the code clean up the old windows struct and lead to the cpu deadloop.It seems some driver is still preventing me from accessing the memory outside the SRAM. Is there something that i miss?

This sounds like something is not patched properly. Copying of PiSmmCpuDxeSmm module might not be sufficient since the version of EDK running on your machine may be way newer than the one we are building on (there might be more security features/renamed ones in newer versions than we have patched). So most likely you need to byte patch them from the dumped firmware image extracted from your mobo. Maybe @pRain1337 can help here, he has done it more recently :)

@Ac1dNe9n
Copy link
Author

Sure. I'll let you know if I come up with a better solution to the above problem.

looks like I need to do some reverse work now. Thanks a lot! 😄

@pRain1337
Copy link
Collaborator

Sure. I'll let you know if I come up with a better solution to the above problem.

looks like I need to do some reverse work now. Thanks a lot! 😄

It could also be that the compiled PiSmmCpuDxeSmm module is not suitable with the rest of the uefi modules on your board, as it's quite old. The patching itself still works, I've done it on a recent z690p board and it works just fine.

Some quick tips for the patch, i can create a more detailed guide on the weekend if you still need help. 😄

I usually patch this variable initialization out and hard code the variable itself to 0 with IDA:
https://github.com/tianocore/edk2/blob/master/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c#L352

Easiest way to find that function (SmmInitPageTable) is to search for the strings of the error messages:
https://github.com/tianocore/edk2/blob/master/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c#L265

Which is referenced multiple times in the SMI Page fault handler:
https://github.com/tianocore/edk2/blob/master/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c#L1003

And the page fault handler is initialized in the same function as the variable initialization (SmmInitPageTable):
https://github.com/tianocore/edk2/blob/master/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c#L442

Hope this helps 😄

@Ac1dNe9n
Copy link
Author

Really appreciate your help. 😄

@Ac1dNe9n
Copy link
Author

Ac1dNe9n commented Jun 20, 2023

Hi, I found the rootkit driver or the SMI handler seems to be unloaded after the full windows boot in my patched MSI PC(Never happened in virtual machine). And I use RWEverything to write data to 0xb2 to trigger the SMI, there is no data output to the serial port, according to the SMI counter in the MSR register, I can confirm that there is an SMI trigger.

I also commented out the rest of the code to only let the serial port output data when SMI is triggered, and found that the serial port output stopped after the complete startup of windows.What i did is finding a SMM Driver using UEFITools and change its PE body with the SMMRookit.efi(I also tried patch different SMM drivers. Same Result). Is there something that i miss?Or do you know how to check the SMI/UEFI driver status?

@pRain1337
Copy link
Collaborator

The missing communication is due to the windows serial driver.
By default, the serial traffic is not being sent / blocked as the driver is stopping the interrupts (that's just a guess, never looked into it that much).

You can get serial output working after windows has started, using two ways:

  1. Rename windows serial driver
    Rename the driver so it won't be loaded on boot, the smm-rootkit can then handle the serial communication.
    C:\Windows\System32\drivers\serial.sys

  2. Open a ssh client (as example putty)
    You can also open the connection using putty or a different serial client, the windows serial driver will stop blocking the connections then. Make sure to select the correct bitrate.

Checking the status else is not really possible without enabling a different communication method.
We've developed a private module that uses a shared memory buffer for communication, I'll add it to this repo when I get time.

@jussihi
Copy link
Owner

jussihi commented Jun 20, 2023

Hmmm, it could be a good idea to also have a FAQ section in the readme for these issues.

@Ac1d-0-0 , It might be that you are the first person ever to really try this on real motherboard besides me and @pRain1337 😄

@Ac1dNe9n
Copy link
Author

Rename windows serial driver
Rename the driver so it won't be loaded on boot, the smm-rootkit can then handle the serial communication.
C:\Windows\System32\drivers\serial.sys

Ah , Looks like I was looking for a solution in the wrong direction.

I can at least successfully run the rootkit in my PC now.(Except the VTOP problem:smile: I will keep trying to find a solution)

Everything works fine in my MSI now.

Beside what you metioned before. I also patched the CommonExceptionHandler's CpuDeadLoop here which caused my MSI board cpu deadloop. They can be find by looking for the string !!!! Can't find image information. !!!!.

Hmmm, it could be a good idea to also have a FAQ section in the readme for these issues.
@Ac1d-0-0 , It might be that you are the first person ever to really try this on real motherboard besides me and @pRain1337 😄

Indeed it could be. The real motherboard test did encounter many unexpected problems. Thanks for you and pRain1337's patient reply. Otherwise I would never be able to solve these problem(Totally wrong direction😆). And, really awesome project! Learned a lot.

@jussihi
Copy link
Owner

jussihi commented Jun 21, 2023

@Ac1d-0-0 great to hear that you got it working,

I will try to make some time to refine the v_memReadMultiPage so that it returns a struct with a bitmap of successfully read pages :-) This way the caller can decide if they want to proceed executing or not if the read bytes does not match the requested number of bytes to be read. I will close this issue once I've fixed that - for now it can remain open.

And of course if you want to implement and test it, feel free to do so and open a pull request :)
´
Thanks for trying out this rootkit, great to hear that it worked in the end!

@pRain1337
Copy link
Collaborator

The missing communication is due to the windows serial driver. By default, the serial traffic is not being sent / blocked as the driver is stopping the interrupts (that's just a guess, never looked into it that much).

You can get serial output working after windows has started, using two ways:

1. Rename windows serial driver
   Rename the driver so it won't be loaded on boot, the smm-rootkit can then handle the serial communication.
   C:\Windows\System32\drivers\serial.sys

2. Open a ssh client (as example putty)
   You can also open the connection using putty or a different serial client, the windows serial driver will stop blocking the connections then. Make sure to select the correct bitrate.

Checking the status else is not really possible without enabling a different communication method. We've developed a private module that uses a shared memory buffer for communication, I'll add it to this repo when I get time.

@Ac1d-0-0
It took a bit longer than expected, but we've released the private module and tested it on the intel z690 chipset.
We've fixed a couple of bugs that we encountered, feel free to check it out :)

https://github.com/pRain1337/Hermes

@Ac1dNe9n
Copy link
Author

Ac1dNe9n commented Aug 27, 2023

Another amazing project :)

I just had a general read through your new code in the memory management section. I didn't seem to see a new solution for this problem in that part of the code. Did i miss something? I will read up on it in a few days.

I've been trying to figure out how to solve that problem above for a long time, but I've realized that it's probably unsolvable for the time being. Because it's hard to get the UEFI code to control Windows memory management code to allocate physical memory to the virtual address I want. So I will definitely get 0 when I do the virtual memory to physical memory conversion.

So my current solution is to not looking for a code cave but just find some code snippet that may not be very useful for the target process and replace it. (Although it will affect the target process, but it ensures that the virtual address will be physically allocated by windows).

@pRain1337
Copy link
Collaborator

The memory management code did not really get any changes, that is true, but the newer code might allow you to develop or find the faulty behavior faster as you can check stuff at runtime with the user mode application.
I can remember that I had the same problem as you had 2 years ago, in my case I was unable to find the kernel entry as all the translations failed without a reason. Are you still using Windows 1909 as you mentioned previously? I think it got solved magically after an update.

@HirbodBehnam
Copy link

I know I'm a little late to the party but I manged to fixed the error by these things:

  1. Installing Windows 10 22H2 instead of 1909. More especially, build 19045.3448 enterprise edition.
  2. Changing the path of the output file to another directory. For example, I used c:\\apps\\smm.txt. You have to change it here. Remember to create the apps folder in C drive!
  3. NOT running the app as administrator.
  4. As mentioned, I've also disabled the hook restoring by deleting these lines.

By doing these, I did manage to trigger the rootkit and replicate everything under QEMU, Ubuntu 22.04, kernel 6.2.0-36!

@jussihi
Copy link
Owner

jussihi commented Nov 8, 2023

I know I'm a little late to the party but I manged to fixed the error by these things:

  1. Installing Windows 10 22H2 instead of 1909. More especially, build 19045.3448 enterprise edition and especially on the newest released version.
  2. Changing the path of the output file to another directory. For example, I used c:\\apps\\smm.txt. You have to change it here. Remember to create the apps folder in C drive!
  3. NOT running the app as administrator.
  4. As mentioned, I've also disabled the hook restoring by deleting these lines.

By doing these, I did manage to trigger the rootkit and replicate everything under QEMU, Ubuntu 22.04, kernel 6.2.0-36!

@HirbodBehnam Hi and thanks for the reply, here are some thoughts, just my 2 cents

  • Changing the Windows version is not really a solution - the rootkit should work on every version.
  • Regarding 2 & 3: yes, this might also work but the reason is that you are not saving the file to C:\ root anymore, but instead a folder that is writable by the user (no admin access required). The user permissions should not matter in regards of rootkit functionality. It only matters here because in the example it is required to have write access to C:\ root.

But anyway, thanks for reporting that 10 22H2 build 19045.3448 enterprise edition. Maybe we will have time some day to compare the newest build of Win11 and the system version you reported and see where they differ and what is causing the crashes in Win11!

@HirbodBehnam
Copy link

@jussihi Yes I do agree. I didn't "fix" anything I just "glued" some stuff together!
I just wrote that comment to inform people who are interested in your project that I did replicate it under those circumstances and if they have problems, maybe they can try those stuff.
Anyway, thanks for the great project. These firmware rootkits are really interesting to me... Hope one day I get the guts to try it on my own PC! Haha

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants