格式化字符串攻击-如何打印argc值?

问题描述

我正在使用C中的格式字符串漏洞,并且尝试通过终端中提供的printf命令打印“ argc”整数的值。

我当前的代码是:

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

char buffer[32];

*More variables*

strncpy(buffer,argv[1],sizeof(buffer));
printf(buffer);

*More printf's*

}

我可能需要使用格式说明符将整数argc的内容打印到终端中,但是我似乎找不到解决方案。我所有的猜测都让我获得了所有argv堆栈寄存器(%rsi,%rdx,%rcx,%r8d,%r9d)。

应在终端中给出格式字符串,如以下示例所示:

./format-string %d_%s

是否可以获取argc值?如果是,该怎么办?

解决方法

我试图在评论中要求一些澄清,但是您没有回答,所以我假设您在符合SYS V x86-64 ABI的环境中工作。

调用main时,argc位于rdi中,但很快被调用strncpyprintf本身覆盖:

main:
    sub     rsp,40
    mov     rsi,QWORD PTR [rsi+8]
    mov     edx,32
    mov     rdi,rsp                 ;OOOPS
    call    strncpy

    mov     rdi,rsp                 ;OOOPS
    xor     eax,eax
    call    printf
    
    xor     eax,eax
    add     rsp,40
    ret

上面的代码是compiled output of your sample program(一旦清除)。

但是,SYS V x86-64 ABI上的glibc本身并不合成argc(就像Windows的副本一样,请参见GetCommandLine等),此值创建程序时将其作为堆栈上的第一个值传递(请参见ABI规范的图3.9)。

Initial program stack

因此,您可以使用printf格式,通过使用%d格式来跳过第一个 k -1个参数,即%k$d,其中 k 是要找到的号码。

要找到k,您只需找到调用rspprintf与地址argc之间的偏移量。
但是,由于argc在创建进程时位于堆栈的底部,所以这等于在调用点rsp的{​​{1}}与的初始值之间找到偏移量。 printf

因此使用gdb:

rsp

现在0x7fffffffdfa0-(0x7fffffffd9d8 + 8)= 0x110

0x110字节是34个参数(0x110 / 8 = 0x22),由于前四个参数在寄存器中,因此我们也需要跳过它们,加4。 最后,计数是基于1的,且包含差值,因此我们需要在计数上加2。 最终值为对于我的示例环境,为34 + 4 + 2 = 40,从而导致命令:

gdb --args format-string test
   b _start
   r
   i r rsp
     0x7fffffffdfa0   The initial value of RSP
   b printf
   c
   i r rsp
     0x7fffffffd9d8 The value AFTER printf is called. Add 8 to find it BEFORE the call
   q
,

printf使用的是系统v x86-64位ABI,该状态指出要传递给函数的所有参数要在寄存器rdi,rsi,rdx,rcx,r8,r9中传递,然后再传递其他值参数(如果存在)以相反的顺序堆栈,因此在您的情况下,您将需要传递多个%p(取决于堆栈上已存在多少数据),并且我们使用%p,因为我们希望将数据打印为64位值。简而言之,将多个%p传递给printf将首先查看寄存器,然后查看存储在堆栈中的参数(从内存中读取)。 所以

%p%p%p%p%p%p%p%p%p  /* will print registers values first extra %p will start to read up from stack (feel free to add as you want but keep in mind it will result in segmentation fault eventually if reached a specific area in memory but not sure when)*/
,

%d用于整数,将%s用于字符串

#include <stdio.h>

int main (int argc,char **argv) 
{
    char buffer[32] = {0};
    strncpy(buffer,argv[1],sizeof(buffer));
    printf("argc = %d and argv[1] = %s\n",argc,buffer);
    return 0;
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...