相关疑难解决方法(0)

当项目中包含程序集文件时,mmap产生了意外的执行权限

我正在用这个把我的头撞到墙上。

在我的项目中,使用mmap映射(/proc/self/maps)分配内存时,尽管我只请求了可读内存,但它仍是一个可读且可执行的区域。

在研究了strace(看起来不错)和其他调试之后,我能够确定似乎唯一可以避免这个奇怪问题的东西:从项目中删除程序集文件,只保留纯C。(什么?!)

所以这是我一个奇怪的例子,我正在使用Ubunbtu 19.04和默认的gcc。

如果使用ASM文件(为空)编译目标可执行文件,则将mmap返回一个可读和可执行区域,如果构建时没有该区域,则它将正常运行。请参阅/proc/self/maps示例中已嵌入的输出。

example.c

#include <stdio.h>
#include <string.h>
#include <sys/mman.h>

int main()
{
    void* p;
    p = mmap(NULL, 8192,PROT_READ,MAP_ANONYMOUS|MAP_PRIVATE,-1,0);

    {
        FILE *f;
        char line[512], s_search[17];
        snprintf(s_search,16,"%lx",(long)p);
        f = fopen("/proc/self/maps","r");
        while (fgets(line,512,f))
        {
            if (strstr(line,s_search)) fputs(line,stderr);
        }

        fclose(f);
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

example.s:是一个空文件!

产出

附带ASM版本

VirtualBox:~/mechanics/build$ gcc example.c example.s -o example && ./example
7f78d6e08000-7f78d6e0a000 r-xp 00000000 00:00 0 
Run Code Online (Sandbox Code Playgroud)

没有ASM随附的版本

VirtualBox:~/mechanics/build$ gcc example.c -o example && ./example
7f1569296000-7f1569298000 …
Run Code Online (Sandbox Code Playgroud)

c linux assembly mmap

94
推荐指数
2
解决办法
2506
查看次数

为什么数据和堆栈段是可执行的?

我刚刚注意到我的简单程序的数据和堆栈段是可执行的.我在/ proc/[pid]/maps中看到了它,简单的代码证实了它.

例如:

; prog.asm
section .data
    code:   db 0xCC    ;int3

section .text
global _start
_start:
    jmp    code

    mov    rax, 60    ; sys_exit
    mov    rdi, 0
    syscall
Run Code Online (Sandbox Code Playgroud)

然后

nasm -f elf64 prog.asm
ld -o prog prog.o
./prog
Run Code Online (Sandbox Code Playgroud)

导致prog执行int3指令.

用C语言编写并用gcc构建的程序使其数据,堆栈和堆不可执行,那么为什么那些用汇编编写的程序会以不同的方式运行?

linux assembly nasm memory-mapping

17
推荐指数
1
解决办法
1543
查看次数

如何获取c代码来执行十六进制字节码?

我想要一个简单的C方法,以便能够在Linux 64位机器上运行十六进制字节码.这是我的C程序:

char code[] = "\x48\x31\xc0";
#include <stdio.h>
int main(int argc, char **argv)
{
        int (*func) ();
        func = (int (*)()) code;
        (int)(*func)();
        printf("%s\n","DONE");
}
Run Code Online (Sandbox Code Playgroud)

我试图运行的代码("\x48\x31\xc0")我通过编写这个简单的汇编程序获得(它不应该真的做任何事情)

.text
.globl _start
_start:
        xorq %rax, %rax
Run Code Online (Sandbox Code Playgroud)

然后编译并objdump它以获取字节码.

但是,当我运行我的C程序时,我得到了一个分段错误.有任何想法吗?

c x86 assembly x86-64 shellcode

9
推荐指数
4
解决办法
1万
查看次数

为什么execstack需要在堆上执行代码?

我编写了下面的代码来测试/tmp/passwd安全类中的赋值的shellcode(用于取消链接).

当我编译时gcc -o test -g test.c,我得到了跳转到shellcode的段错误.

当我使用后处理二进制文件时execstack -s test,我不再获得段错误并且shellcode正确执行,删除/tmp/passwd.

我运行gcc 4.7.2.为了使堆可执行,似乎要求堆栈是可执行的似乎是个坏主意,因为后者比前者有更多合法的用例.

这是预期的行为吗?如果是这样,理由是什么?

#include <stdio.h>                                     
#include <stdlib.h>                                    


char* shellcode;                                       


int main(){                                            
    shellcode = malloc(67);                            
    FILE* code = fopen("shellcode.bin", "rb");      
    fread(shellcode, 1, 67, code);                     

    int (*fp)(void) = (int (*) (void)) shellcode;      
    fp();                                              
}    
Run Code Online (Sandbox Code Playgroud)

这是输出xxd shellcode.bin:

0000000: eb28 5e89 760c 31c0 8846 0bfe c0fe c0fe  .(^.v.1..F......           
0000010: c0fe c0fe c0fe c0fe c0fe c0fe c0fe c089  ................           
0000020: f3cd 8031 db89 d840 …
Run Code Online (Sandbox Code Playgroud)

c gcc

6
推荐指数
2
解决办法
6384
查看次数

如何以编程方式告诉Linux处于PAE或非PAE模式?

需要创建一个脚本来检查内核是否处于PAE模式.当然,仅检查/ proc/cpuinfo标志是否具有此"pae"设置是不够的.

我们必须知道PAE机制是否实际上不仅实现了,而且还被激活.

因为PAE内核现在是新的默认值,如果你需要一个非PAE内核,那么现在必须创建另一个内核.

  1. 换句话说,我们如何判断内核在具有PAE的CPU上是否是非PAE(是测试的两个可能条件之一).

  2. 另一个是,如何在没有PAE支持的CPU上判断内核是否为PAE.

并且没有办法判断在典型的安全内核中是否使用了CONFIG_HIGHMEM或CONFIG_PAE内核配置选项.

memory kernel memory-management cpu-architecture linux-kernel

5
推荐指数
1
解决办法
1998
查看次数

在 PT_GNU_STACK 程序头上设置执行位时,为什么进程的所有段都变为可执行

在控制段上的可执行位的过程中,我发现了PT_GNU_STACK加载程序如何使用的一个巨大的怪癖。

根据elf(5)联机帮助页,PT_GNU_STACK用作:

GNU 扩展,Linux 内核使用它通过 p_flags 成员中设置的标志来控制堆栈的状态。

execstack手册页,也支持这一点:

... ELF 二进制文件和共享库现在可以标记为需要或不需要可执行堆栈。此标记是通过 PT_GNU_STACK 程序头条目中的 p_flags 字段完成的。

但是,除了设置堆栈可执行文件之外,当我设置该位时,几乎所有段都变为可执行文件。

例如,当我运行时sleep,我得到了这个内存映射

sleep 100 & cat /proc/$!/maps
[1] 1260
561460d8d000-561460d94000 r-xp 00000000 08:01 524383                     /bin/sleep
561460f94000-561460f95000 r--p 00007000 08:01 524383                     /bin/sleep
561460f95000-561460f96000 rw-p 00008000 08:01 524383                     /bin/sleep
561462eca000-561462eeb000 rw-p 00000000 00:00 0                          [heap]
7f02b08b9000-7f02b0b97000 r--p 00000000 08:01 1966102                    /usr/lib/locale/locale-archive
7f02b0b97000-7f02b0d7e000 r-xp 00000000 08:01 655384                     /lib/x86_64-linux-gnu/libc-2.27.so
7f02b0d7e000-7f02b0f7e000 ---p 001e7000 08:01 655384                     /lib/x86_64-linux-gnu/libc-2.27.so
7f02b0f7e000-7f02b0f82000 r--p …
Run Code Online (Sandbox Code Playgroud)

linux glibc elf ld

5
推荐指数
1
解决办法
174
查看次数

如何从 C / 汇编中的内存地址执行函数?

我有以下汇编函数(已用 objdump 显示)

0000000000000000 <add>:
   0:   b8 06 00 00 00          mov    $0x6,%eax
   5:   c3                      retq  
Run Code Online (Sandbox Code Playgroud)

现在在 CI 中做了以下代码:

#include <stdio.h>

typedef int (*funcp) (int x);

unsigned char foo[] = {0xb8,0x06,0x00,0x00,0x00,0xc3};

int main(void)
{
  int i;
  funcp f = (funcp)foo;
  i = (*f);
  
  printf("exit = %d\n", i);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

在全局变量 foo 中,我在汇编中输入了我的函数的内存地址并尝试执行它,但它没有按预期返回 6。如何为它们的内存地址执行函数?此外,我可以在哪里研究更多关于该主题的信息?

obs:有时我会遇到 Segmentation fault (core dumped) 错误

c linux x86 assembly disassembly

5
推荐指数
1
解决办法
105
查看次数

在.text部分中定义只读数据的原因是什么?

我正在学习汇编和低级编程,并阅读有关它.据说我们可以将任何数据放在elf文件的.text部分中,但当然我们不能因为页面/段的不同权限而改变它.但是没有告诉那里,因为在.text部分内部有数据的原因是什么.许多C++程序员也告诉我g ++编译器

static const char DATA[] = "SOME DATA";
Run Code Online (Sandbox Code Playgroud)

也在.text部分内.我想知道,为什么不将这些数据放在.rodata部分,目的是什么?如果使用.text,那么.rodata中应该存储什么?

主要问题是在长模式下的这种行为.

c++ assembly

4
推荐指数
1
解决办法
341
查看次数

gcc execstack标志究竟允许在什么情况下使用,以及如何执行呢?

我这里有一些示例代码,用于理解初学者CTF的某些C行为:

// example.c

#include <stdio.h>


void main() {
        void (*print)();

        print = getenv("EGG");
        print();
}
Run Code Online (Sandbox Code Playgroud)

编译: gcc -z execstack -g -m32 -o example example.c

用法: EGG=$(echo -ne '\x90\xc3) ./example

如果我用execstack标志编译代码,则程序将执行我在上面注入的操作码。没有该标志,该程序将由于分段错误而崩溃。

为什么会这样呢?是因为getenv将实际的操作码存储在堆栈上,而execstack标志允许跳转到堆栈吗?还是getenv将指针推入堆栈,关于内存的哪些部分可执行的还有其他一些规则?我阅读了联机帮助页,但是我无法确切了解规则是什么以及如何执行它们。

另一个问题是,我认为我确实也缺少在调试时可视化内存的好工具,因此很难弄清楚这一点。任何建议将不胜感激。

c x86 gcc

3
推荐指数
1
解决办法
242
查看次数

为什么linux内核将我的RW段映射为RWX?

我有一个非常简单的ELF可执行文件:

$ readelf -l ./plt.out

Elf file type is EXEC (Executable file)
Entry point 0x400338
There are 7 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x00000000003ff040 0x00000000003ff040
                 0x0000000000000188 0x0000000000000188  R E    8
  LOAD           0x0000000000000000 0x00000000003ff000 0x00000000003ff000
                 0x0000000000001000 0x0000000000001000  RW     1000
  INTERP         0x00000000000001c8 0x00000000003ff1c8 0x00000000003ff1c8
                 0x0000000000000032 0x0000000000000032  R      1
      [Requesting program interpreter: /data/keno/new_glibc/usr/lib/ld-linux-x86-64.so.2]
  LOAD           0x0000000000001000 0x0000000000400000 0x0000000000400000
                 0x00000000000003b0 0x00000000000003b0  R E    1000
  LOAD           0x0000000000001ea0 0x0000000000600ea0 0x0000000000600ea0
                 0x0000000000000180 0x0000000000000180  RW     1000 …
Run Code Online (Sandbox Code Playgroud)

linux glibc dynamic-linking linux-kernel

1
推荐指数
1
解决办法
339
查看次数

x86_64 汇编中的分段错误,代码位于 .text 节中:(节名称中带有冒号)

为什么会出现分段错误?

我用的nasm -f elf64 t.asm -o t.o ld t.o -o t是linux下的编译。

我已经做了我能想到的一切。

section .data:
  variable_int db 1
  variable_string db "yaaaa", 10
section .text:
  global _start
_start:
  mov rax, 1
  mov rdi, 1
  mov rsi, variable_string
  mov rdx, 14
  syscall
  mov rax, 60
  mov rdi, 0
  syscall
Run Code Online (Sandbox Code Playgroud)

assembly x86-64 nasm segmentation-fault

1
推荐指数
1
解决办法
372
查看次数

汇编部分 .code 和 .text 的行为不同

我是汇编新手,从我了解到的情况.code与 相同.text,但下面的代码将使用.code.

segment .data
    msg db "hello, world", 0xa
    len equ $ - msg

section .text
    global _start

_start:
    mov edx, len
    mov ecx, msg

    mov ebx, 1
    mov eax, 4
    int 0x80

    mov ebx, 0
    mov eax, 1
    int 0x80

Run Code Online (Sandbox Code Playgroud)
nasm -f elf64 -o hello.o hello.s 
ld -s -o hello hello.o
hello, world

sed -i s/.text/.code/ ./hello.s
nasm -f elf64 -o hello.o hello.s 
ld -s -o hello hello.o
./stack.sh: line 8:  4621 Segmentation …
Run Code Online (Sandbox Code Playgroud)

assembly x86-64 nasm elf

0
推荐指数
1
解决办法
378
查看次数