some thing about the kernel32.dll base address in X64

文章转自http://www.x64asm.com/Charme/article/content/art1.html

 

some thing about the kernel32.dll base address in X64
---2010.1.19 20:30---
32:

之前在病毒里涉及到很多时候都要用kernel32.dll的基址

通过这个基址搜索EAT来获得导出函数LoadLibrary和GetProcAddress

然后利用这两个函数获取其他的函数,当然也可以直接搜索导出表获得想要的函数!

现在装了win7,测试之前写的病毒不起作用,调试发现基址是错误的!虽然是64位系统,但是Wow64下面应

该是可以运行的!
所以确定必然是基址的获得方法有改变。


第一种方法-------------
xor ebx, ebx
mov ebx, fs:[ 0x30 ]    ;PEB
mov ebx, [ ebx + 0x0C ] ;PEB->Ldr
mov ebx, [ ebx + 0x1C ] ;PEB->Ldr.InInitializationOrderModuleList.Flink
mov ebx, [ ebx ]        ;next entry
mov ebx, [ ebx + 0x08 ] ;base address (kernel32.dll)

在xp vista 2000上都是这样的!运行没有问题!

 


但是win7上面在加载kernel32.dll之前要先加载kernelbase.dll

所以mov ebx,[ebx]的时候实际上是接近了kernelbase.dll

所以要获得kernel32.dll我们需要修正下之前的做法

第二种方法:

xor ebx, ebx
mov ebx, fs:[ 0x30 ]       ;PEB
mov ebx, [ ebx + 0x0C ]    ;PEB->Ldr
mov ebx, [ ebx + 0x14 ]    ;PEB->Ldr.InMemoryOrderModuleList.Flink (1st entry)
mov ebx, [ ebx ]           ;next entry (2nd entry)
mov ebx, [ ebx ]           ;entry (3rd entry)
mov ebx, [ ebx + 0x10 ]    ;base address (kernel32.dll)

但是我的一个外国朋友bitRAKE说,这样貌似在2000上有些时候是失效的,问题就在
InMemoryOrderModuleList的地址上!

更为妥当而且稳定的方法是这样的(多做一些判断):

第三种方法:
cld
xor edx, edx

mov edx, [fs:edx+0x30]  ;PEB
mov edx, [edx+0x0C]     ;PEB->Ldr
mov edx, [edx+0x14]     ;;PEB->Ldr.InMemoryOrderModuleList.Flink (1st entry)
next_mod:
mov esi, [edx+0x28]     ;modules name (unicode string)
push byte 24            ;push down the length we want to check
pop ecx
xor edi, edi            ;store the hash of the module name
loop_modname:
xor eax, eax
lodsb
cmp al, 'a'             ;some versions of Windows use lower case module names
jl not_lowercase
sub al, 0x20            ;up
not_lowercase:
ror edi, 13
add edi, eax            ;add the next byte of the name to the hash
loop loop_modname
cmp edi, 0x6A4ABC5B     ;compare the hash with that of KERNEL32.DLL
mov ebx, [edx+0x10]     ;get this modules base address
mov edx, [edx]          ;get the next module
jne next_mod

现在ebx里面就是kernel32的基址

那么在我们写个程序在我当前的系统上做个测试(win7 x64)
测试结果是这样的:
-------------------------------------------------------------
GetModuleHandleA( "kernelbase.dll" ) = 0x75030000
GetModuleHandleA( "kernel32.dll" )   = 0x75360000
GetModuleHandleA( "ntdll.dll" )      = 0x76F20000
-------------------------------------------------------------
Method 1: Kernel32 Base Address = 0x75030000 (Correct: NO!)
Method 2: Kernel32 Base Address = 0x75360000 (Correct: YES)
Method 3: Kernel32 Base Address = 0x75360000 (Correct: YES)
-------------------------------------------------------------

很显然之前的方法一是不行了。呼呼!!

 

这样的方法是比较稳妥的。

64:
我跟bitRAKE说,我想研究64位,他回答我说,你根本没有必要专门的来研究64.
只需要找到你最拿手的领域稍微的修改下就可以了!
我有点感叹,中国人看到64不敢尝试,甚至排斥,说什么现在32呢还早呢!!!
根本不是一个思路想问题,那么我们也这样的来尝试下,仅仅把64作为一个稍微改进了的机制。
不要把它认为是多么难搞的东西!

具体的64 的东西我不提,第一,我也初涉及,第二,有的是官方文档。

貌似国外的derko针对x64写过类似的东西,而且也进行了其他几个方面的研究
(要承认国外研究64比我们要早,这不可否认)是这样的:

  xor rdx, rdx             ; Zero rdx
  mov rdx, [gs:rdx+96]     ; Get a pointer to the PEB
  mov rdx, [rdx+24]        ; Get PEB->Ldr
  mov rdx, [rdx+32]        ; Get the first module from the InMemoryOrder module list
next_mod:                  ;
  mov rsi, [rdx+80]        ; Get pointer to modules name (unicode string)
  movzx rcx, word [rdx+74] ; Set rcx to the length we want to check
  xor r9, r9               ; Clear r9 which will store the hash of the module name
loop_modname:              ;
  xor rax, rax             ; Clear rax
  lodsb                    ; Read in the next byte of the name
  cmp al, 'a'              ; Some versions of Windows use lower case module names
  jl not_lowercase         ;
  sub al, 0x20             ; If so normalise to uppercase
not_lowercase:             ;
  ror r9d, 13              ; Rotate right our hash value
  add r9d, eax             ; Add the next byte of the name
  loop loop_modname        ; Loop untill we have read enough
  ; We now have the module hash computed
  push rdx                 ; Save the current position in the module list for later
  push r9                  ; Save the current module hash for later
  ; Proceed to itterate the export address table,
  mov rdx, [rdx+32]        ; Get this modules base address
 
 
我用fasm写过一个测试程序,上面的方法没有成功!

fdbg跟踪了下:
0000000000402018 65488B5260 GS mov rdx,[rdx+60] ; [000007FFFFFDE060]

=000007FFFFFD3000
这里应该是PEB的地址

我用windbg查看的时候貌似看到peb应该是在000007fffffda000,,所以这里没有获得有效的东西!

可是又想,win7里面有动态基址的技术(是win7 不是64 cpu)
也就是说PEB的地址对于不同的进程是不一样的!
我拿起windbg有看了下,peb at 000007fffffd8000,,,,,,,,法克and史特

那么想到用函数来动态的获取!
NtCurrentTeb?呼呼。然后从teb获取peb!!
貌似这样做是克瑞科特的!


我还是不心甘,简单修改了下上面那个:
mov rax,[gs:30h]  ; RAX points to TEB (Thread Environment Block)
mov rcx,[rax+60h] ; RCX points to PEB (Process Environment Block)

考虑代码的优化,也可以这样写:
        push 60h
        pop rsi
        gs lodsq ; RAX points to PEB
       
我写了个测试的程序:

;-----------------------------------------------------------------------------;
; Author: charme (http://www.x64asm.com/)
; Compatible: Windows 7(i only test about this,OTHER maybe)
; Architecture: x64
; Size: 3kb
;-----------------------------------------------------------------------------;

;then our coce start,have a fun!

format  PE64 GUI

include 'C:/asm/tool/fasm/fasmw/INCLUDE/win64axp.inc'
                                                   
                                                    
                                                     

.data
crc     db      400h    dup     (?)
sz      db      'charme',0
szformat  db    'baseaddr=0x%.16IX',0
buff    rb      1024
.code
start:
        ;;stack
        cld

        sub     rsp,8*(4+4-1)       ;bcs the .code macro has 'sub rsp,8h'

 

        push    rsi
        push    60h
        pop     rsi
        gs      lodsq ; RAX points to PEB
        mov     rdx,rax
        mov     rdx,[rdx+24]        ;PEB->Ldr
        mov     rdx,[rdx+32]        ;first module(InMemoryOrder module list)

 


next_mod:                  ;
        mov     rsi, [rdx+80]        ; Get pointer to modules name (unicode string)
        movzx   rcx, word [rdx+74]   ; Set rcx to the length we want to check

        xor     r9, r9               ; Clear r9 which will store the hash of the module name
loop_modname:             
        xor     rax, rax             ; Clear rax
        lodsb                        ; Read in the next byte of the name
        cmp     al, 'a'              ; Some versions of Windows use lower case module names
        jl      not_lowercase        
        sub     al, 0x20             ; If so normalise to uppercase
not_lowercase:            
        ror     r9d, 13              ; Rotate right our hash value
        add     r9d, eax

 

        dec     rcx
        test    rcx,rcx
        jne     loop_modname


        cmp     r9d,092af16dah       ;kernel32.dll
        jne     _next
        mov     RbX,[RDX+32]

 

        xchg    rbx,rax


        lea     rcx,[buff]
        lea     rdx,[szformat]
        mov     r8,rax
        call    [wsprintf]

        xor     r9,r9
        lea     r8,[sz]
        lea     rdx,[buff]

        xor     rcx,rcx
        call    [MessageBoxA]
        jmp     _exit

_next:
        mov     rdx,[rdx]
        jmp     next_mod

 

_exit:
        add     rcx,8*(4+4-1)
        xor     rcx,rcx
        call    [ExitProcess]

.end    start


输出结果:
baseaddr:000000076B20000H


我还没有搭建好windbg!没有办法验证!不过我估计是没有问题的!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值