c# linux shell,关于C#:Linux Shellcode“ Hello,World!”

我有以下工作的NASM代码:

global _start

section .text

_start:

mov eax, 0x4

mov ebx, 0x1

mov ecx, message

mov edx, 0xF

int 0x80

mov eax, 0x1

mov ebx, 0x0

int 0x80

section .data

message: db"Hello, World!", 0dh, 0ah

在屏幕上显示" Hello,World! n"。 我还具有以下C包装器,其中包含先前的NASM对象代码:

char code[] =

"\xb8\x04\x00\x00\x00"

"\xbb\x01\x00\x00\x00"

"\xb9\x00\x00\x00\x00"

"\xba\x0f\x00\x00\x00"

"\xcd\x80\xb8\x01\x00"

"\x00\x00\xbb\x00\x00"

"\x00\x00\xcd\x80";

int main(void)

{

(*(void(*)())code)();

}

但是,当我运行代码时,似乎未执行汇编代码,但程序退出正常。 有任何想法吗?

谢谢

注入此shellcode时,您不知道message的含义:

mov ecx, message

在注入的过程中,它可以是任何值,但不能为"Hello world!

",因为当您仅转储文本部分时,它位于数据部分中。您可以看到您的shellcode没有"Hello world!

":

"\xb8\x04\x00\x00\x00"

"\xbb\x01\x00\x00\x00"

"\xb9\x00\x00\x00\x00"

"\xba\x0f\x00\x00\x00"

"\xcd\x80\xb8\x01\x00"

"\x00\x00\xbb\x00\x00"

"\x00\x00\xcd\x80";

这是Shellcode开发中的常见问题,解决方法是这样的:

global _start

section .text

_start:

jmp MESSAGE      ; 1) lets jump to MESSAGE

GOBACK:

mov eax, 0x4

mov ebx, 0x1

pop ecx          ; 3) we are poping into `ecx`, now we have the

; address of"Hello, World!

"

mov edx, 0xF

int 0x80

mov eax, 0x1

mov ebx, 0x0

int 0x80

MESSAGE:

call GOBACK       ; 2) we are going back, since we used `call`, that means

; the return address, which is in this case the address

; of"Hello, World!

", is pushed into the stack.

db"Hello, World!", 0dh, 0ah

section .data

现在转储文本部分:

$ nasm -f elf shellcode.asm

$ ld shellcode.o -o shellcode

$ ./shellcode

Hello, World!

$ objdump -d shellcode

shellcode:     file format elf32-i386

Disassembly of section .text:

08048060 <_start>:

8048060:   e9 1e 00 00 00   jmp    8048083

08048065 :

8048065:   b8 04 00 00 00   mov    $0x4,%eax

804806a:   bb 01 00 00 00   mov    $0x1,%ebx

804806f:   59               pop    %ecx

8048070:   ba 0f 00 00 00   mov    $0xf,%edx

8048075:   cd 80            int    $0x80

8048077:   b8 01 00 00 00   mov    $0x1,%eax

804807c:   bb 00 00 00 00   mov    $0x0,%ebx

8048081:   cd 80            int    $0x80

08048083 :

8048083:   e8 dd ff ff ff   call   8048065

8048088:   48               dec    %eax                    

8048089:   65               gs                               |

804808a:   6c               insb   (%dx),%es:(%edi)          |

804808b:   6c               insb   (%dx),%es:(%edi)          |

804808c:   6f               outsl  %ds:(%esi),(%dx)          |

804808d:   2c 20            sub    $0x20,%al                 |

804808f:   57               push   %edi                      |

8048090:   6f               outsl  %ds:(%esi),(%dx)          |

8048091:   72 6c            jb     80480ff    |

8048093:   64               fs                               |

8048094:   21               .byte 0x21                       |

8048095:   0d               .byte 0xd                        |

8048096:   0a               .byte 0xa                      

$

我标记的行是我们的"Hello, World!

"字符串:

$ printf"\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21\x0d\x0a"

Hello, World!

$

因此,我们的C包装器将是:

char code[] =

"\xe9\x1e\x00\x00\x00"  //          jmp    8048083

"\xb8\x04\x00\x00\x00"  //          mov    $0x4,%eax

"\xbb\x01\x00\x00\x00"  //          mov    $0x1,%ebx

"\x59"                  //          pop    %ecx

"\xba\x0f\x00\x00\x00"  //          mov    $0xf,%edx

"\xcd\x80"              //          int    $0x80

"\xb8\x01\x00\x00\x00"  //          mov    $0x1,%eax

"\xbb\x00\x00\x00\x00"  //          mov    $0x0,%ebx

"\xcd\x80"              //          int    $0x80

"\xe8\xdd\xff\xff\xff"  //          call   8048065

"Hello wolrd!

";     // OR      "\x48\x65\x6c\x6c\x6f\x2c\x20\x57"

//         "\x6f\x72\x6c\x64\x21\x0d\x0a"

int main(int argc, char **argv)

{

(*(void(*)())code)();

return 0;

}

让我们测试一下:

$ gcc test.c -o test

$ ./test

Hello wolrd!

$

有用。

不知道为什么您没有得到任何投票,但这是一个很好的答案。 谢谢您的帮助。

应该删除空字节以执行Shellcode

@REALFREE如果您使用的函数需要以null结尾的字符串(如字符串函数strcpy),则空字节将是一个问题,它将无法读取整个shellcode,字符串。 否则就可以了。

如BSH所述,您的shellcode不包含消息字节。跳转到message标签并在定义msg字节之前调用GOBACK例程是一个不错的选择,因为msg的地址将在栈顶作为返回地址,可以弹出到ecx ,其中存储了味精的地址。

但是您和BSH的代码都有一些限制。

它包含NULL bytes ( \x00 ),当被函数指针取消引用时,它会被视为字符串的结尾。

有一种解决方法。您存储在eax, ebx and edx中的值足够小,可以分别访问al, bl and dl一次将其直接写入各个寄存器的低半字节。

高半字节可能包含垃圾值,因此可以对其进行异或。

b8 04 00 00 00 ------ mov $0x4,%eax

变成

b0 04          ------ mov $0x4,%al

31 c0          ------ xor    %eax,%eax

与先前的指令集不同,新的指令集不包含任何NULL字节。

因此,最终程序如下所示:

global _start

section .text

_start:

jmp message

proc:

xor eax, eax

mov al, 0x04

xor ebx, ebx

mov bl, 0x01

pop ecx

xor edx, edx

mov dl, 0x16

int 0x80

xor eax, eax

mov al, 0x01

xor ebx, ebx

mov bl, 0x01   ; return 1

int 0x80

message:

call proc

msg db" y0u sp34k 1337 ?"

section .data

组装和链接:

$ nasm -f elf hello.asm -o hello.o

$ ld -s -m elf_i386 hello.o -o hello

$ ./hello

y0u sp34k 1337 ? $

现在从hello二进制文件中提取shellcode:

$ for i in `objdump -d hello | tr '\t' ' ' | tr ' ' '

' | egrep '^[0-9a-f]{2}$' ` ; do echo -n"\\x$i" ; done

输出:

\xeb\x19\x31\xc0\xb0\x04\x31\xdb\xb3\x01\x59\x31\xd2\xb2\x12\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xb3\x01\xcd\x80\xe8\xe2\xff\xff\xff\x20\x79\x30\x75\x20\x73\x70\x33\x34\x6b\x20\x31\x33\x33\x37\x20\x3f\x20

现在,我们可以使用我们的驱动程序来启动Shellcode。

#include

char shellcode[] ="\xeb\x19\x31\xc0\xb0\x04\x31\xdb"

"\xb3\x01\x59\x31\xd2\xb2\x12\xcd"

"\x80\x31\xc0\xb0\x01\x31\xdb\xb3"

"\x01\xcd\x80\xe8\xe2\xff\xff\xff"

"\x20\x79\x30\x75\x20\x73\x70\x33"

"\x34\x6b\x20\x31\x33\x33\x37\x20"

"\x3f\x20";

int main(int argc, char **argv) {

(*(void(*)())shellcode)();

return 0;

}

现代编译器中有某些安全功能,例如NX保护,可防止执行数据段或堆栈中的代码。因此,我们应该明确指定编译器以禁用这些功能。

$ gcc -g -Wall -fno-stack-protector -z execstack launcher.c -o launcher

现在,可以调用launcher来启动Shellcode。

$ ./launcher

y0u sp34k 1337 ? $

对于更复杂的shellcode,会有另一个障碍。现代Linux内核具有ASLR或Address Space Layout Randomization

您可能需要在注入shellcode之前将其禁用,尤其是当它通过缓冲区溢出时。

root@localhost:~# echo 0 > /proc/sys/kernel/randomize_va_space

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值