Assembly/Shellcode 获取系统(主机)名称
Assembly/Shellcode getting system (host)name
所以,对于学校的一门课程,我们试图找到一个汇编代码,它可以找到系统主机名(即当 运行 "hostname" 或 "uname -n" 在终端)。
但是经过大量谷歌搜索后,我们被卡住了。问题是,代码随后将被转换为 shellcode,但对于我们尝试过的所有版本,它都会导致分段错误。通常我们会写一个小的 C 程序,组装它然后使用 gdb 将它写入 shellcode。
而且我们总是以分段错误告终。
那么,关于如何尽可能简单地通过汇编找到系统主机名,有什么建议吗? (运行 Ubuntu x86 通过 VirtualBox)
其次,有什么想法可以错误检查导致分段错误的当前 shellcode 吗? (运行 堆栈中的可执行代码已启用)
非常感谢,有任何问题!
"new uname" 系统调用 returns 以下结构:
#define __NEW_UTS_LEN 64
struct new_utsname {
char sysname[__NEW_UTS_LEN + 1];
char nodename[__NEW_UTS_LEN + 1];
char release[__NEW_UTS_LEN + 1];
char version[__NEW_UTS_LEN + 1];
char machine[__NEW_UTS_LEN + 1];
char domainname[__NEW_UTS_LEN + 1];
};
这意味着我们需要为结构分配至少 390 个字节,并且 nodename
从偏移量 65 开始。在 32 位 linux 上,uname 系统调用是 #122
。因此,独立代码可能如下所示:
xor %eax, %eax # eax=0
sub 2, %eax # eax=-sys_uname
lea (%esp, %eax, 4), %esp # allocate buffer
neg %eax # fix sign of sys_uname
mov %esp, %ebx # address of the buffer
int [=11=]x80 # syscall
mov , %al # sys_write (assume eax==0)
lea -3(%eax), %ebx # stdout (1)
lea 65(%esp), %ecx # address of nodename
lea 60(%eax), %edx # length (do strlen if you want)
int [=11=]x80 # syscall
mov , %al # sys_exit
int [=11=]x80 # syscall
这将打印整个 nodename
,因此包括一堆尾随零(通常不可见)。确定确切的字符串长度留作练习 ;)
这是与位置无关(零字节自由)的代码,只需获取机器代码字节并将其复制到堆栈中就可以使其作为 shellcode 工作(假设您所说的可执行堆栈):
void main()
{
char code[] = {
0x31, 0xc0, 0x83, 0xe8, 0x7a, 0x8d, 0x24, 0x84,
0xf7, 0xd8, 0x89, 0xe3, 0xcd, 0x80, 0xb0, 0x04,
0x8d, 0x58, 0xfd, 0x8d, 0x4c, 0x24, 0x41, 0x8d,
0x50, 0x3c, 0xcd, 0x80, 0xb0, 0x01, 0xcd, 0x80 };
((void(*)())code)();
}
使用gcc -m32 -z execstack
编译。
所以,对于学校的一门课程,我们试图找到一个汇编代码,它可以找到系统主机名(即当 运行 "hostname" 或 "uname -n" 在终端)。
但是经过大量谷歌搜索后,我们被卡住了。问题是,代码随后将被转换为 shellcode,但对于我们尝试过的所有版本,它都会导致分段错误。通常我们会写一个小的 C 程序,组装它然后使用 gdb 将它写入 shellcode。
而且我们总是以分段错误告终。
那么,关于如何尽可能简单地通过汇编找到系统主机名,有什么建议吗? (运行 Ubuntu x86 通过 VirtualBox)
其次,有什么想法可以错误检查导致分段错误的当前 shellcode 吗? (运行 堆栈中的可执行代码已启用)
非常感谢,有任何问题!
"new uname" 系统调用 returns 以下结构:
#define __NEW_UTS_LEN 64
struct new_utsname {
char sysname[__NEW_UTS_LEN + 1];
char nodename[__NEW_UTS_LEN + 1];
char release[__NEW_UTS_LEN + 1];
char version[__NEW_UTS_LEN + 1];
char machine[__NEW_UTS_LEN + 1];
char domainname[__NEW_UTS_LEN + 1];
};
这意味着我们需要为结构分配至少 390 个字节,并且 nodename
从偏移量 65 开始。在 32 位 linux 上,uname 系统调用是 #122
。因此,独立代码可能如下所示:
xor %eax, %eax # eax=0
sub 2, %eax # eax=-sys_uname
lea (%esp, %eax, 4), %esp # allocate buffer
neg %eax # fix sign of sys_uname
mov %esp, %ebx # address of the buffer
int [=11=]x80 # syscall
mov , %al # sys_write (assume eax==0)
lea -3(%eax), %ebx # stdout (1)
lea 65(%esp), %ecx # address of nodename
lea 60(%eax), %edx # length (do strlen if you want)
int [=11=]x80 # syscall
mov , %al # sys_exit
int [=11=]x80 # syscall
这将打印整个 nodename
,因此包括一堆尾随零(通常不可见)。确定确切的字符串长度留作练习 ;)
这是与位置无关(零字节自由)的代码,只需获取机器代码字节并将其复制到堆栈中就可以使其作为 shellcode 工作(假设您所说的可执行堆栈):
void main()
{
char code[] = {
0x31, 0xc0, 0x83, 0xe8, 0x7a, 0x8d, 0x24, 0x84,
0xf7, 0xd8, 0x89, 0xe3, 0xcd, 0x80, 0xb0, 0x04,
0x8d, 0x58, 0xfd, 0x8d, 0x4c, 0x24, 0x41, 0x8d,
0x50, 0x3c, 0xcd, 0x80, 0xb0, 0x01, 0xcd, 0x80 };
((void(*)())code)();
}
使用gcc -m32 -z execstack
编译。