首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >格式化字符串攻击-如何打印argc值?

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

Stack Overflow用户
提问于 2020-10-18 19:15:01
回答 3查看 324关注 0票数 1

我正在处理C中的格式字符串漏洞,并试图通过终端中给定的printf命令打印"argc“整数的值。

我当前的代码是:

代码语言:javascript
复制
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)。

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

代码语言:javascript
复制
./format-string %d_%s

是否有可能获得ARGC值?如果是,我该怎么做?

EN

回答 3

Stack Overflow用户

发布于 2020-10-18 20:28:39

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

当调用main时,argcrdi中,但很快就会被对strncpyprintf本身的调用覆盖:

代码语言:javascript
复制
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 (清理后)。

但是,SYSVx86-64ABI上的glibc不会合成argc本身(就像Windows的对应产品一样,请参阅GetCommandLine和类似的内容),在创建程序时,该值将作为堆栈上的第一个值传递(请参阅ABI规范的图3.9 )。

因此,您可以通过使用跳过前k-1个参数的%d格式,即%k$d,通过printf达到它,其中k是要找到的数字。

要查找k,您只需找到调用printf时的rspargc地址之间的偏移量。

但是,因为在创建进程时argc位于堆栈的底部,所以这相当于查找printf调用点的rsprsp的初始值之间的偏移量。

所以使用gdb:

代码语言:javascript
复制
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

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

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

代码语言:javascript
复制
./format-string '%40$d'
票数 3
EN

Stack Overflow用户

发布于 2020-10-18 19:50:42

printf使用system v x86-64位ABI,它规定要在寄存器rdi、rsi、rdx、rcx、r8、r9中传递的函数的所有参数,如果存在,则进一步的值参数将以相反的顺序传递到堆栈,因此在您的情况下,您将需要传递多个%p (取决于堆栈上已存在的数据数量),我们使用%p,因为我们希望将数据打印为64位值。简而言之,将多个%p传递给printf将首先查看寄存器,然后查看存储到堆栈中的参数(从内存中读取)。所以

代码语言:javascript
复制
%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)*/
票数 0
EN

Stack Overflow用户

发布于 2020-10-18 19:18:58

整数使用%d,字符串使用%s

代码语言:javascript
复制
#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;
}
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64412632

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档