|
[Original]
[Print]
[Top]
|
以下是自修改的源代码,在Red Hat AS3.0上运行正常。
在AS4.0上,除了 test("code", (PfnVoid)in_code); 可以运行通过以外,另外三个都不可以,也就是MEMCPY_TEST(data); MEMCPY_TEST(heap); 和MEMCPY_TEST(stack);
出错的地方都在test函数里的 code(); 上。
都是收到信号:SIGSEGV,错误:Segmentation Fault。
我现在迫切需要的是让MEMCPY_TEST(heap)可以运行过去,也就是new出来的数组可以运行,请高手指点。
//自修改的代码:self_Modify.c
#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
const unsigned char in_code[]
__attribute__ (( aligned(8), section(".text") )) =
{
0x53, /* 00000000: push ebx */
0x6A,0x04, /* 00000001: push byte +0x4 */
0x58, /* 00000003: pop eax */
0x31,0xDB, /* 00000004: xor ebx,ebx */
0x43, /* 00000006: inc ebx */
0xB9,0x01,0x80,0x04,0x08, /* 00000007: mov ecx,0x8048001 */
0x6A,0x03, /* 0000000C: push byte +0x3 */
0x5A, /* 0000000E: pop edx */
0xCD,0x80, /* 0000000F: int 0x80 */
0x5B, /* 00000011: pop ebx */
0xC3 /* 00000012: ret */
}; /* 19 bytes (0x13) */
typedef void (*PfnVoid)(void);
#define MEMCPY_TEST(where)
memcpy(in_##where, in_code, sizeof(in_code));
test(#where, (PfnVoid)in_##where)
static jmp_buf env;
static int received_sigill = 0;
static void on_sigill(int sig)
{
printf(" on_sigill=%d ", sig);
received_sigill = 1;
longjmp(env, 1);
}
static void test(const char* name, PfnVoid code)
{
printf("%8p is %s ... ", code, name);
fflush(stdout);
received_sigill = 0;
if (0 == setjmp(env))
{
signal(SIGILL, on_sigill);
code();
}
printf(" sigill=%d
", received_sigill);
}
static char in_data[sizeof(in_code)];
int main()
{
char* in_heap = malloc(sizeof(in_code));
char in_stack[sizeof(in_code)];
test("code", (PfnVoid)in_code);
MEMCPY_TEST(data);
MEMCPY_TEST(heap);
MEMCPY_TEST(stack);
return 0;
}
|
|
|
[Original]
[Print]
[Top]
|
|
[Original]
[Print]
[Top]
|
分配出来的内存在权限上都没有EXEC 所以一运行就报错了
建议或者用mprotect将那一部分内存权限改为PROT_READ | PROT_WRITE | PROT_EXEC
或者用mmap分配内存 直接指定权限为PROT_READ | PROT_WRITE | PROT_EXEC
具体2个函数的使用看man或者搜一下 介绍很多
|
|
|
----
读了这么多年的书 还是觉得幼儿园好混
|
|
[Original]
[Print]
[Top]
|
|
[Original]
[Print]
[Top]
|
作为IA32对页面的保护机制,每个页都有一系列的FLAG来标识别它是否允许,读,写或执行(具体可以看INTEL IA32 SDM-1部分关于页表 的介绍),而NEW出来的页面一般是存在于HEAP中的,也就是默认是DATA,DATA一般认为是(R+W) && ( ! X )的~所以你可以想个办法设置一下。
比如WIN32下我们可以这么做~XP SP2下也没问题~呵呵~
#include "stdafx.h"
#include <windows.h>
long pfoo( long num, char* str, void* ptr )
{
long local = 100 * num;
__asm{ nop } __asm{ nop } __asm{ nop } __asm{ nop }
__asm{ nop } __asm{ nop } __asm{ nop } __asm{ nop }
printf("num=%d local=%d str=%s ptr=0x%08x
", num, local, str, ptr );
MessageBox( NULL,"OK!!!!!!!!!", ":)", MB_OK );
__asm{ nop } __asm{ nop } __asm{ nop } __asm{ nop }
__asm{ nop } __asm{ nop } __asm{ nop } __asm{ nop }
return num * 99;
}
long pfoo2( long num, char* str, void* ptr )
{
printf("Memory Changed!!
" );
MessageBox( NULL,"OK!!!!!!!!!",":)", MB_OK );
return 12345678;
}
typedef long (*XFT_FOO)( long, char*, void* );
MEMORY_BASIC_INFORMATION*
__fastcall
AllocProcedure( MEMORY_BASIC_INFORMATION& src,
MEMORY_BASIC_INFORMATION& dst,
void* ptr )
{
return ( !ptr ||
!VirtualQuery( ptr, &src, sizeof(src) ) ||
!src.RegionSize ||
IsBadCodePtr( (FARPROC)ptr ) ||
!( dst.BaseAddress = VirtualAlloc( NULL,
src.RegionSize,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE ) ) ||
!( VirtualQuery( dst.BaseAddress, &dst, sizeof(dst) )
) ? NULL : &dst );
}
void*
__fastcall CopyProcedure( void* ptr,
MEMORY_BASIC_INFORMATION& dst )
{
MEMORY_BASIC_INFORMATION src = { 0 };
return ( !ptr ||
!VirtualQuery( ptr, &src, sizeof(src) ) ||
!dst.BaseAddress ||
dst.RegionSize < src.RegionSize ||
IsBadCodePtr( (FARPROC)ptr ) ||
IsBadWritePtr( dst.BaseAddress, dst.RegionSize )
)? NULL : memcpy( dst.BaseAddress, ptr, src.RegionSize ) ;
}
bool
__fastcall SetProperty( MEMORY_BASIC_INFORMATION& proc,
DWORD protect = PAGE_EXECUTE_READWRITE )
{
return !!VirtualProtect( proc.BaseAddress,
proc.RegionSize,
protect,
&proc.Protect );
}
void*
__fastcall FreeProcedure( MEMORY_BASIC_INFORMATION& proc )
{
return ( !proc.BaseAddress
) ? NULL : VirtualAlloc( proc.BaseAddress,
proc.RegionSize,
MEM_RESET,
PAGE_NOACCESS ) ;
}
int main(int argc, char* argv[])
{
MEMORY_BASIC_INFORMATION foo1 = { 0 };
MEMORY_BASIC_INFORMATION foo2 = { 0 };
MEMORY_BASIC_INFORMATION dst = { 0 };
foo1.BaseAddress = pfoo;
foo2.BaseAddress = pfoo2;
//
// Caution:
// the CopyProcedure and AllocProcedure procedure are both work wtih a
// hole page's allocated size(the exe image's size ). u may fix it
// working with the function body size:
// sizeof(prolog code) + sizeof(procedure code) + sizeof(epilog code).
//
long k =0;
XFT_FOO ptr = 0;
if( AllocProcedure( foo1, dst, pfoo ) )
{
ptr = ((XFT_FOO) CopyProcedure( pfoo, dst ));
k = ptr( 0,"Hello World!", (void*)(0x66666666));
printf( "First Time: foo=0x%08x foo2=0x%08x ptr=0x%08x k=%d
", pfoo,pfoo2, ptr, k );
ptr = ((XFT_FOO) CopyProcedure( pfoo2, dst ));
k = ptr( 0,0, (void*)(0));
printf( "Last Time: foo=0x%08x foo2=0x%08x ptr=0x%08x k=%d
", pfoo,pfoo2, ptr, k );
FreeProcedure( dst );
}
return 0;
}
|
|
|
[Original]
[Print]
[Top]
|
|