Malware Journey Day 37–40

Nick Mckenney
8 min readJan 19, 2024

--

This malware blog would be too short split into days

I was working on how to use a dll. Below is the code

Here is my main

We have LoadLibraryA and GetProcAddress. I paired these 2 together because really they work in sync. All loadlibrary does is give me the handle to this dll. This handle gives me control to close or open a file. Or perhaps allow me to control a dll.

This is the DLL

I export this dll and make it reachable via “CreateNotepad”
The shellcode below is just opening up notepad.exe

To open up something I learned from previous malware triage that the order of functions through WINAPI is always VirtualAlloc and VirutalProtect first. This allocates memory space and sets the protections of how it is executed. CreateThread is usually requiring me to attach another process through the debugger when I hit it. The winAPI I expect to hit with this will eventually be NtResumeThread

The below Bool APIENTRY DLLMain is standard for all DLLs created in visual studio code

Now I admit that this dll has a bit too many functions. I was more of just practicing to see what this would look like when I analyze the executable.

Time to throw it in IDA!

I hit the above first

When debugging my own code Ive been seeing a lot of

JMC_flag
CheckForDebuggerJustMyCode

According to microsoft

“debugging feature that automatically steps over calls to system”

So I first examine LoadLibraryA -> This is what my “malware” is using to load the DLL

Since it only takes in one input being lpLibFileName

This is my path to the DLL. thats all this pointer is doing for me. Normally FindResource would be more apportiate, Ill cover that later.

Notice this

What is happening here since LoadLibraryA returns a handle to the module, itll be set in rax.

Since registers change, this is storing it in an offset to the base register. It adds hModule to not overwrite any exisiting offset due to an unpredicatable size of the handle.

Next is GetProcAddress

FARPROC GetProcAddress(
[in] HMODULE hModule,
[in] LPCSTR lpProcName
);

Its clear that its grabbing the handle from the returned previous function. The procName is just a string

Now in Memory

I am starting with LoadLibraryA

Since we know its take one input which will be from the rcx register

Time to step into this call. Im more curious on how it creates a handle. This is again because GetProcAddress uses it

I am seeing this first

I really dont understand what is happening from the top of this function to the call of LoadLibraryExA

I figured out eventually that all this is doing is prepping to get a handle by calling LoadLibraryExA.

In the fast call I need to look at 3 registers

hFile must be null

since no flag is set, this function is just LoadLibraryA

Stepping into LoadLibraryExA now

Looks like I missed it. The return from LoadLibraryExW gave us the handle. Restarting

Nothing showed to be interesting until hitting this function

“Address of MZ header in virtual memory of caller’s process.”

Thanks MalApi.io for this!

Basically it seems this is loading a dll into memory, in this case my custom dll.

When moving into this function I dont see much of anything special. Lots of moving things between registers and the stack have 3 items pushed to it of value 0.

I jump into a random call and I see a reference to a MZ header for my project.exe. I figure this out by following the first address in memory map which leads me to project.exe

When going through more calls I finally found where my createnotepadprocess.dll is being loaded

At address rcx+30

This is then eventually moved to RDX

It is here where the return register gets set to the proper handle

Finally I have escaped the call to LoadLibraryExA

I came with a pointer to my dll.

Now I am back at my main function with a reference that will be stored in the offset rbp+8

Now time for GetProcAddress

From Ida I can see that the first option pushed is the return register which came from LoadLibraryA

The second option is just the process string name

Stepping into the function

What IDA doesnt show me is

Now I could just dump the RAX and follow in memory map. Then grab the binary for the dll. That would allow me to analyze this dll. GetProcAddressForCaller

When Googling “how does GetProcAddressForCaller help GetProcAddress”

I see nothing. Prehaps I can make a guess through x64dbg

My inital plan is to dump every effective address I see

This appears to me the binary for the dll

I step into this call next

So far nothing interesting in LdrGetProcedureAddress

from google it is “function that retrieves the address of an exported function”
though I saw nothing like that when going through the assembly

When returning from this function I couldnt find the address of the exported function.

It appears my program has though

the address at offset 0x48 from rbp is the pointer to my exported function.

Looks like I found my shellcode

As a reminder here is my code for the dll

It appears that right after the shellcode being loaded into rbp at offset x we call virtualalloc

Above is the inputs to the function I am about to step into

0 -> Null

117 → length of shellcode

3000 -> MEM_COMIT…..

040-> PAGE_READWRITE

Really all I expect to happen is get a page of null bytes

As expected, we get the null bytes. When returning from this function the next steps will be

It appears this is RtlMoveMemory just relocated my shellcode into the virtualAlloc function

So for reference right now

offset 0x10 is my shellcode

offset 0x168 is my virtualAlloc empty space right now

What ever was moved to register r10 is a vcrunetime dll.

All this is for is Visual Studio to run smooth.

After going through this function I didnt find anything. Time to redo

At the very beginning it is moving my virtualAlloc space to the rax register

Here it appears to be comparing my open virtualAlloc space to my shellcode

What ever this is

It is loading it into my virtualAlloc space

Now when returning back to my main function I have my shellcode allocated, but no protections are set

VirtualProtect

This was rather short. I didnt find much change it did to the dll or my shellcode page

After VirtualProtect we have

At CreateThread I can see that it has the start address of my shellcode

It will return a handle to this thread

Finally at my function WaitingforSingleObject Ill call the handle

As expected my notepad opens at this function

--

--

No responses yet