1024programmer Asp.Net How to extract volatile method arguments from x64 programs

How to extract volatile method arguments from x64 programs

How to extract volatile method parameters of x64 programs

one: background

1. Storytelling

Recently, I often encounter feedback from friends on how to extract method parameters in the thread stack in the x64 environment. Friends who are familiar with the x64 calling protocol should know that under this protocol, the first four parameters of the method are passed in registers. For example, there are four registers rcx, rdx, r8d, r9d. Due to the temporary nature of the register value, its value is easily used by the subsequent logic. Is there any way to do this in this case? What about extracting it? To be honest, it all depends on luck. Why do you say that? If this is temporarily saved in the thread stack during the stack initialization process of the method, congratulations, you can successfully fish it out.

Let’s talk in depth through a small case.

Two: Case Analysis

1. A case demonstration

For the convenience of description, here I use Marshal to allocate heap blocks on ntheap, and then extract the user handle of the Marshal.FreeHGlobal method. The reference code is as follows:


         static void Main(string[] args)
         {
             //1. Allocate heap blocks
             IntPtr ptr = Marshal.AllocHGlobal(sizeof(int));
             Console.WriteLine("ptr= 0x{0:X2}", ptr);

             //2. Write data
             var num = int.MaxValue;
             Marshal.WriteInt32(ptr, num);
             Console.WriteLine("num has been written to ptr= 0x{0:X2} heap block", ptr);
             Debugger.Break();

             //3. Release the heap block
             Marshal.FreeHGlobal(ptr);
             Console.WriteLine("ptr= 0x{0:X2} heap block released successfully", ptr);
         }

 

Friends who are familiar with ntheap know that if you use the FreeHGlobal method in a debugging environment, it will hit the underlying ntdll!RtlpValidateHeap method. Just set a breakpoint here. That’s it, the reference code is as follows:


 0:000>bp ntdll!RtlpValidateHeap
 0:000> g
 Breakpoint 0 hit
 ntdll!RtlpValidateHeap:
 00007ffe`8e92a784 48895c2410 mov qword ptr [rsp+10h],rbx ss:00000021`2037e078=00007ffd00000000
 0:000> k 10
  # Child-SP RetAddr Call Site
 00 00000021`2037e068 00007ffe`8e9295f5 ntdll!RtlpValidateHeap
 01 00000021`2037e070 00007ffe`8e855cc1 ntdll!RtlDebugFreeHeap+0x99
 02 00000021`2037e0d0 00007ffe`8e855b74 ntdll!RtlpFreeHeap+0xc1
 03 00000021`2037e280 00007ffe`8e8547b1 ntdll!RtlpFreeHeapInternal+0x464
 04 00000021`2037e340 00007ffe`8c33934f ntdll!RtlFreeHeap+0x51
 05 00000021`2037e380 00007ffd`d4af5c7c KERNELBASE!LocalFree+0x2f
 06 00000021`2037e3c0 00007ffd`7b132a10 System_Private_CoreLib!System.Runtime.InteropServices.Marshal.FreeHGlobal+0x4c [/_/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Windows.cs @ 144] 
 07 00000021`2037e490 00007ffd`dacaae93 Example_18_1_1!Example_18_1_1.Program.Main+0xd0 [D:\skyfly\18.20230322\src\Example\Example_18_1_1\Program.cs @ 21]
 ...

 

You can see from the code that this function is called when the heap block is released. Next, there is a requirement. I want to know what the first parameter of KERNELBASE!LocalFree is. Some friends are sure I want to say that you can get the rcx register, but don’t forget that at this time the code runs to the ntdll!RtlpValidateHeap method, in rcx The value has long been overwritten by other methods, so what should I do?

2. Is there still hope

Whether there is any hope really depends on luck. At this time, you should carefully observe the assembly code at the entrance of the KERNELBASE!LocalFree method to see if it saves rcx in the stack. If so, If you save it to the stack, you’ll be lucky. Once you have an idea, just do it.


 0:000> u KERNELBASE!LocalFree
 KERNELBASE!LocalFree:
 00007ffe`8c339320 48895c2410 mov qword ptr [rsp+10h],rbx
 00007ffe`8c339325 4889742418 mov qword ptr [rsp+18h],rsi
 00007ffe`8c33932a 48894c2408 mov qword ptr [rsp+8],rcx
 00007ffe`8c33932f 57 push rdi
 00007ffe`8c339330 4883ec30 sub rsp,30h
 00007ffe`8c339334 488bd9 mov rbx,rcx
 00007ffe`8c339337 f6c308 test bl,8
 00007ffe`8c33933a 753f jne KERNELBASE!LocalFree+0x5b (00007ffe`8c33937b)

 

Looking at the assembly code, we are really lucky. The code saves rcx to the stack location of rsp+8. Next, we urgently need to know the rsp+ here. Which memory address does 8 refer to?

3. Where does rsp+8 point to?

Under the x64 platform, in order to maximize the use of registers, the method stack frame uses an rsp to mark the stack space, unlike the 32bit platform which uses ebp and esp Two registers to jointly carry, refer to the k command output.


 0:000> k 8
  # Child-SP RetAddr Call Site
 00 00000021`2037e068 00007ffe`8e9295f5 ntdll!RtlpValidateHeap
 01 00000021`2037e070 00007ffe`8e855cc1 ntdll!RtlDebugFreeHeap+0x99
 02 00000021`2037e0d0 00007ffe`8e855b74 ntdll!RtlpFreeHeap+0xc1
 03 00000021`2037e280 00007ffe`8e8547b1 ntdll!RtlpFreeHeapInternal+0x464
 04 00000021`2037e340 00007ffe`8c33934f ntdll!RtlFreeHeap+0x51
 05 00000021`2037e380 00007ffd`d4af5c7c KERNELBASE!LocalFree+0x2f
 06 00000021`2037e3c0 00007ffd`7b132a10 System_Private_CoreLib!System.Runtime.InteropServices.Marshal.FreeHGlobal+0x4c [/_/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Windows.cs @ 144] 
 07 00000021`2037e490 00007ffd`dacaae93 Example_18_1_1!Example_18_1_1.Program.Main+0xd0 [D:\skyfly\18.20230322\src\Example\Example_18_1_1\Program.cs @ 21]

 

The next question is: What is the relationship between Child-SP and rsp in the KERNELBASE!LocalFree method? To answer this question, you need to be very clear about how Child-SP marks stack frames. Draw a picture as follows:

It can be clearly seen from the picture: Child-SP marks the position of the first parameter in the sub-method, and the RSP at the method entrance points to the return address RIP of the method. The position is one pointer unit smaller than Child-SP.

Some friends may ask why the RIP is located. This is because the assembly call instruction will be implicitly executed as follows.


 PUSH RIP
 SUB ESP,8

 

After having these foundations, the next step will be easier. The calculation formula is:

rsp = Child-SP - 0x8

Then rsp + 0x8 = Child-SP - 0x8 + 0x8 = Child-SP = 000000212037e3c0, then use windbg to verify.


 0:000>dp 000000212037e3c0 L1
 00000021`2037e3c0 00000141`a81f1f20
 0:000> !heap -x 00000141`a81f1f20
 Entry User Heap Segment Size PrevSize Unused Flags
 --------------------------------------------------  --------------------------------------------------  ----------
 00000141a81f1f10 00000141a81f1f20 00000141a8100000 00000141a8100000 40 90 3c busy extra fill

 

Looking back at the output of the Console interface, it turned out to be the ptr= 0x141A81F1F20 address that I was looking for.

Three: Summary

This is a very useful experience sharing post. I believe you will definitely use it in dump analysis. Generally speaking, since the method parameters are passed through registers, whether you can successfully obtain them requires you to carefully observe the assembly code. Only then can we know.

The good things in the world can be obtained by those who believe.

Picture name

This article is from the internet and does not represent1024programmerPosition, please indicate the source when reprinting:https://www.1024programmer.com/how-to-extract-volatile-method-arguments-from-x64-programs/

author: admin

Previous article
Next article

Leave a Reply

Your email address will not be published. Required fields are marked *

Contact Us

Contact us

181-3619-1160

Online consultation: QQ交谈

E-mail: [email protected]

Working hours: Monday to Friday, 9:00-17:30, holidays off

Follow wechat
Scan wechat and follow us

Scan wechat and follow us

Follow Weibo
Back to top
首页
微信
电话
搜索