A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about user-mode development.
 #27020  by puzzlex
 Tue Oct 20, 2015 12:33 pm
Operating system is Windows 10 (64 bit). I am playing with dnsapi.dll, I modified it by adding a small assembly code into the end of .text section.
I patched one of the exported functions to jump to that code and when I call OutputDebugStringA or any other API it just crashes right away due to an access violation somewhere in ntdll.dll. Here is my code:
Code: Select all
format PE64 GUI

start:		push	rcx					; this is my hook handler function, this is where the JMP lands
		push	rdx					; saving registers
		push	r8
		push	r9
		push	rsi
		push	rdi

		call	delta					; delta
delta:		pop	rsi
		mov	rdi, rsi
		and	rdi, 0ffffffffffff0000h

search:		cmp	dword [rdi], 905a4dh			; find image base
		jz	found
		sub	rdi, 10000h
		jmp	search

found:		lea	rcx, [rsi + dnshook - delta]		; load my dll
		xor	rdx, rdx ; reserved, always zero
		mov	r8, 800h ; flag
		;call	qword [rdi + 78310h]			; LoadLibraryExW (as imported in dnshook.dll at offset 78310). If i remove the comment it crashes.

		lea	rax, [rdi + 0d940h + 5]			; offset of original function
		pop	rdi					; restoring registers
		pop	rsi
		pop	r9
		pop	r8
		pop	rdx
		pop	rcx

		push	rbp					; these are the bytes that I copied from the original function (I have overwritten with a JMP instruction)
		push	rbx
		push	rsi
		push	rdi
		jmp	rax					; jmp back to original function

dnshook		du	'test.dll', 0

In the above I used LoadLibraryExA, but I tried with OutpuDebugStringA as well (it was imported by dnsapi.dll too). If I comment out the call to the API it works perfectly, but if I leave it there it crashed. In debugger everything seems perfect, I cannot think of anything else what could be the problem?

Note: in order to replace system file I updated the checksum in the PE header of my new dll and taken ownership of the old DLL and then replaced it.
 #27023  by feryno
 Wed Oct 21, 2015 8:30 am
When you use ring3 debugger to obtain RSP, is it aligned at 16 at the time of calling API from your code? Thats at address of
Code: Select all
call   qword [rdi + 78310h]         ; LoadLibraryExW
If not, then change your prologue to this
Code: Select all
start:
      push   rcx               ; this is my hook handler function, this is where the JMP lands
      push   rdx               ; saving registers
      push   r8
      push   r9
      push   rsi
      push   rdi
      sub    rsp,8*5
if the above helps, then also update you epilogue
 #27024  by puzzlex
 Wed Oct 21, 2015 9:26 am
Indeed this was the problem!! Thanks so much!

From the documentation:
At a minimum, each function must reserve 32 bytes (four 64-bit values) on the stack. This space allows registers passed into the function to be easily copied to a well-known stack location. The callee function isn't required to spill the input register params to the stack, but the stack space reservation ensures that it can if needed.