URN Logo
UNIX Resources » Linux » China Linux Forum » CPU 与 编译器 » 7 » 自修改代码如何在AS4.0上正常运行?
announcement 声明: 本页内容为中国Linux论坛的内容镜像,文章的版权以及其他所有的相关权利属于中国Linux论坛和相应文章的作者,如果转载,请注明文章来源及相关版权信息。
Resources
China Linux Forum(finished)
Linux Forum(finished)
FreeBSD China(finished)
linuxforum.net
  业界新闻与评论
  自由软件杂谈
  IT 人生
  Linux软件快递
  翻译作坊
  Linux图书与评论
  GNU Emacs/XEmacs
  Linux 中文环境和中文化
  Linux桌面与办公软件
  Linux 多媒体与娱乐版
  自由之窗Mozilla
  笔记本电脑上的Linux
  Gentoo
  Debian 一族
  网络管理技术
  Linux 安装与入门
  WEB服务器和FTP服务器
  域名服务器和邮件服务器
  Linux防火墙和代理服务器应用
  文件及打印服务器
  技术培训与认证
  Linux内核技术
  Linux 嵌入技术
  Linux设备驱动程序
  Linux 集群技术
  LINUX平台数据库
  系统和网络安全
  CPU 与 编译器
  系统计算研究所专栏
  Linux下的GUI软件开发
  C/C++编程版
  PHP 技 术
  Java&jsp技术
  Shell编程技术
  Perl 编 程
  Python 编 程
  XML/Web Service 技术
  永远的Unix
  FreeBSD世界
   
自修改代码如何在AS4.0上正常运行?
 
Re: 自修改代码如何在AS4.0上正常运行? - Xtim [2005-08-18 11:52 | 4,830 byte(s)]
 
 
Subject: 自修改代码如何在AS4.0上正常运行?
Author: hanyuqiang0612    Posted: 2005-08-12 09:34    Length: 2,989 byte(s)
[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]
Subject: Re: 自修改代码如何在AS4.0上正常运行?
Author: teawater    Posted: 2005-08-12 10:07    Length: 263 byte(s)
[Original] [Print] [Top]
分配出来的内存在权限上都没有EXEC 所以一运行就报错了
建议或者用mprotect将那一部分内存权限改为PROT_READ | PROT_WRITE | PROT_EXEC
或者用mmap分配内存 直接指定权限为PROT_READ | PROT_WRITE | PROT_EXEC
具体2个函数的使用看man或者搜一下 介绍很多
----
读了这么多年的书 还是觉得幼儿园好混
[Original] [Print] [Top]
Subject: Re: 自修改代码如何在AS4.0上正常运行?
Author: Xtim    Posted: 2005-08-18 11:52    Length: 4,830 byte(s)
[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]
« Previous thread
微处理器软核的价格通常是多少?
CPU 与 编译器
7
Next thread »
如何将new出来的数组放到代码段?
     

Copyright © 2007 UNIX Resources Network, All Rights Reserved.      About URN | Privacy & Legal | Help | Contact us
备案序号: 京ICP备05006143    webmaster: webmaster@unixresources.net
This page created on 2008-07-17 03:47:24, cost 0.041406869888306 ms.