利用FS寄存器得到任意函数地址

[plain]  view plain copy
  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
  2. ;  
  3. ;       程序函数说明:利用fs寄存器,得到任意的函数地址  
  4. ;               by:瀚 海    2011年11月19日  
  5. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
  6. ;  
  7. ;很早之前就知道利用fs可以导出kernel32!LoadLibrary、Kernel32!GetProcAddress函数  
  8. ;也就可以得到任意dll的任意函数,一直不清楚到底哪个数据偏移多少位置。最近开始弄安全  
  9. ;所以顺便弄下shellcode  
  10. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
  11.         .386  
  12.         .model  flat,stdcall  
  13.         option casemap:none  
  14. include     windows.inc  
  15.   
  16.         .data  
  17. DllName     db      'ExitProcess',0  
  18.   
  19.         .data?  
  20. Count       dd          ?  
  21.   
  22. assume  fs:nothing      ;打开FS寄存器,否则用到FS寄存器的编译都不会通过  
  23.         .code  
  24.   
  25. ;得到字符串长度  
  26. ;相同返回0,不同返回1,便于后面可以使用C语言库的strcmp函数  
  27. strcmp      proc uses edi esi ebx ecx  source:dword,dst:dword  
  28.         xor     eax,eax  
  29.         ;判断来源是不是有NLL地址,如果有,直接当成不等字符串  
  30.         mov     esi,source  
  31.         test    esi,esi  
  32.         je      NotEQual  
  33.         mov     edi,dst  
  34.         test    edi,edi  
  35.         je      NotEQual  
  36.         ;判断两字符是否有为'\0'结尾的字符串,有一个不为'\0'则将继续比较  
  37.         ;直到遇到不等字符或两个都为'\0'字符  
  38.     cmpNext:  
  39.         mov     bl,byte ptr[esi]  
  40.         test    bl,bl  
  41.         jnz     TestNextZ  
  42.         cmp     byte ptr[edi],0  
  43.         je      szEqual ;两字符串都以'\0'结尾,那么他们是相同字符串  
  44.     TestNextZ:  
  45.         mov     cl,byte ptr[edi]  
  46.         inc     edi  
  47.         inc     esi  
  48.         cmp     bl,cl  
  49.         jnz     NotEQual  
  50.         jmp     cmpNext  
  51.     NotEQual:  
  52.         inc     eax  
  53.     szEqual:  
  54.         ret  
  55. strcmp      endp  
  56.   
  57. ;得到字符串长度函数  
  58. ;这个函数在其他地方copy的  
  59. strlen  proc    uses ecx edi szString:dword  
  60.         mov     edi,szString  
  61.         xor     ecx,ecx  
  62.         dec     ecx  
  63.         xor     al,al  
  64.         repne   scasb  
  65.         not     ecx  
  66.         dec     ecx  
  67.         xchg    eax,ecx  
  68.         ret  
  69. strlen  endp  
  70.   
  71. ;得到任意函数地址  
  72. ;如果函数不在Kernel32.dll中可以利用LoadLibrary、GetProcAddress加载其他函数  
  73. GetProcessAddress   proc    uses edx esi ecx ebx dllName:DWORD  
  74.         mov     eax,dword ptr fs:[30H] ;得到TEB结构  
  75.         mov     eax,dword ptr [eax+0CH] ;得到PEB_LDR_DATA结构  
  76.         mov     esi,dword ptr [eax+1CH] ;InInitializationOrderModuleList  
  77.         ;得到Kernel32.dll所在LDR_MODEL结构的InInitializationOrderModuleList地址  
  78.         lodsd     
  79.         mov     edx,dword ptr[eax+8H]   ;得到BaseAddress,即kernel32基址  
  80.         push    edx  
  81.         mov     ecx,dword ptr[edx+3CH] ;edx指向kernel32的内存映像基址,得到PE头指针  
  82.         lea     ecx,dword ptr[edx+ecx] ;ecx,指向PE头  
  83.         mov     ecx,dword ptr[ecx+78H] ;指向导出表  
  84.         lea     ecx,dword ptr[edx+ecx] ;ecx指向导出表  
  85.         mov     ebx,dword ptr[ecx+1CH]  
  86.         lea     ebx,dword ptr[edx+ebx] ;ebx指向函数地址列表  
  87.         push    ebx ;先保存函数地址列表首地址  
  88.         mov     ebx,dword ptr[ecx+0CH]      ;网上有说这个地址是偏移0x20的,不清楚是不是系统版本问题  
  89.         lea     ebx,dword ptr[edx+ebx] ;ebx指向函数名称列表,第一个是kernel32.dll  
  90. ;       push    ebx     ;有必要的话,可以保存下  
  91.     @@:  
  92.         inc     Count       ;函数序号+1  
  93.         mov     eax,Count  
  94.         cmp     eax,3BBH    ;XP中只有954个函数,超过的就错误了  
  95.         jge     @F  
  96.         invoke  strlen,ebx  
  97.         ;ebx指向下一个字符串首地址,第一次指向"kernel32.dll"字符串  
  98.         lea     ebx,dword ptr[eax+ebx+1]  
  99.         invoke  strcmp,dllName,ebx  ;比较字符串,相同返回0  
  100.         cmp     eax,0  
  101.         jnz     @B  
  102.         dec     Count           ;得到函数的序号,也可以当成是函数表中的第几个函数  
  103.         mov     eax,Count  
  104.         shl     eax,2           ;每个地址32位,所以要乘以4  
  105.         pop     ebx             ;弹出函数地址列表首地址  
  106.         mov     ebx,dword ptr[ebx+eax]      ;得到函数的偏移地址  
  107.         pop     edx             ;弹出kernel32首地址  
  108.         lea     eax,dword ptr[edx+ebx]      ;得到函数地址  
  109.     @@:  
  110.         ret  
  111. GetProcessAddress   endp  
  112.   
  113. start:  
  114.         xor     eax,eax  
  115.         mov     Count,eax  
  116.         ;调用查找函数地址函数,返回eax中是函数地址,如果函数不存在返回小于0xFFFFF的值  
  117.         invoke  GetProcessAddress,offset DllName  
  118.         .if  eax > 0FFFFFH  
  119.             push    NULL  
  120.             call    eax ;调用ExitProcess函数  
  121.         .endif  
  122.         ;如果没有这个函数,那么手动处理错误  
  123. end start  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值