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

妖狐艹你老母 2022-08-10 08:46 212阅读 0赞

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

发表评论

表情:
评论列表 (有 0 条评论,212人围观)

还没有评论,来说两句吧...

相关阅读

    相关 STM32从地址寄存器

    本文希望在[上一节][Link 1]的基础上,把指针操作过渡到寄存器的使用,来帮助读者深入理解寄存器。 引入头文件 主函数里出现了强制转换与指针的操作,程序不那么容易理