首页
社区
课程
招聘
[求助]软件加密内幕中一个程序编译不能通过
发表于: 2008-9-12 10:34 4556

[求助]软件加密内幕中一个程序编译不能通过

2008-9-12 10:34
4556
软件加密技术内幕中由一个修改PE文件的程序,如下,我编译不过,还请高手赐教。
错误是C:\Program Files\Microsoft Visual Studio\MyProjects\pe\pe.cpp(201) : error C2065: 'filename' : undeclared identifier

//writePE.cpp

#include <windows.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <SYS\STAT.H>

void printaddress();
void map_exe(const void *base);
void writefile();

unsigned char writeline[18]={
0x6a,0x40,0x6a,0x0,0x6a,0x0,0x6a,0x0,0xe8,0x01,0x0,0x0,0x0,0xe9,0x0,0x0,0x0,0x0
};

DWORD space;
DWORD entryaddress;
DWORD entrywrite;
DWORD progRAV;
DWORD oldentryaddress;
DWORD newentryaddress;
DWORD codeoffset;
DWORD peaddress;
DWORD flagaddress;
DWORD flags;

DWORD virtsize;
DWORD physaddress;
DWORD physsize;
DWORD MessageBoxAadaddress;

int main(int argc,char * * argv)
{
        HANDLE hFile, hMapping;
        void *basepointer;
        FILETIME * Createtime;
        FILETIME * Accesstime;
        FILETIME * Writetime;
        Createtime = new FILETIME;
        Accesstime = new FILETIME;
        Writetime = new FILETIME;

        if ((hFile = CreateFile(argv[1], GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0)) == INVALID_HANDLE_VALUE)//打开要修改的文件
        {
                puts("(could not open)");
                return EXIT_FAILURE;
        }
        if(!GetFileTime(hFile,Createtime,Accesstime,Writetime))
        {
                printf("\nerror getfiletime: %d\n",GetLastError());
        }
        //得到要修改文件的创建、修改等时间
        if (!(hMapping = CreateFileMapping(hFile, 0, PAGE_READONLY | SEC_COMMIT, 0, 0, 0)))
        {
                puts("(mapping failed)");
                CloseHandle(hFile);
                return EXIT_FAILURE;
        }
        if (!(basepointer = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0)))
        {
                puts("(view failed)");
                CloseHandle(hMapping);
                CloseHandle(hFile);
                return EXIT_FAILURE;
        }
        //把文件头映象存入baseointer
        CloseHandle(hMapping);
        CloseHandle(hFile);
        map_exe(basepointer);//得到相关地址
        UnmapViewOfFile(basepointer);
        printaddress();
        printf("\n\n");
        if(space<50)
        {
                printf("\n空隙太小,数据不能写入.\n");
        }       
        else
        {
                writefile();//写文件
        }

        if ((hFile = CreateFile(argv[1], GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0)) == INVALID_HANDLE_VALUE)
        {
                puts("(could not open)");
                return EXIT_FAILURE;
        }

        if(!SetFileTime(hFile,Createtime,Accesstime,Writetime))
        {
                printf("error settime : %d\n",GetLastError());
        }
        //恢复修改后文件的建立时间等
        delete Createtime;
        delete Accesstime;
        delete Writetime;
        CloseHandle(hFile);
        return 0;
}

void map_exe(const void *base)
{
        IMAGE_DOS_HEADER * dos_head;
        dos_head =(IMAGE_DOS_HEADER *)base;
        #include <pshpack1.h>
        typedef struct PE_HEADER_MAP
        {
        DWORD signature;
        IMAGE_FILE_HEADER _head;
        IMAGE_OPTIONAL_HEADER opt_head;
        IMAGE_SECTION_HEADER section_header[];
        } peHeader;
        #include <poppack.h>
       
        if (dos_head->e_magic != IMAGE_DOS_SIGNATURE)
        {
                puts("unknown type of file");
                return;
        }

        peHeader * header;
        header = (peHeader *)((char *)dos_head + dos_head->e_lfanew);//得到PE文件头
        if (IsBadReadPtr(header, sizeof(*header)))
        {
                puts("(no PE header, probably DOS executable)");
                return;
        }

        DWORD mods;
        char tmpstr[4]={0};
        DWORD tmpaddress;
        DWORD tmpaddress1;

        if(strstr((const char *)header->section_header[0].Name,".text")!=NULL)
        {
                virtsize=header->section_header[0].Misc.VirtualSize;
                //此段的真实长度
                physaddress=header->section_header[0].PointerToRawData;
                //此段的物理偏移
                physsize=header->section_header[0].SizeOfRawData;
                //此段的物理长度
                peaddress=dos_head->e_lfanew;
                //得到PE文件头的开始偏移

                peHeader peH;
                tmpaddress=(unsigned long )&peH;
                //得到结构的偏移
                tmpaddress1=(unsigned long )&(peH.section_header[0].Characteristics);
                //得到变量的偏移
                flagaddress=tmpaddress1-tmpaddress+2;
                //得到属性的相对偏移
                flags=0x8000;
                //一般情况下,“.text”段是不可读写的,如果我们要把数据写入这个段需要改变其属性,实际上这个程序并没有把数据写入“.text”段,所以并不需要更改,但如果你实现复杂的功能,肯定需要数据,肯定需要更改这个值,

                space=physsize-virtsize;
                //得到代码段的可用空间,用以判断可不可以写入我们的代码
                //用此段的物理长度减去此段的真实长度就可以得到
                progRAV=header->opt_head.ImageBase;
                //得到程序的装载地址,一般为400000
                codeoffset=header->opt_head.BaseOfCode-physaddress;
                //得到代码偏移,用代码段起始RVA减去此段的物理偏移
                //应为程序的入口计算公式是一个相对的偏移地址,计算公式为:
                //代码的写入地址+codeoffset

                entrywrite=header->section_header[0].PointerToRawData+header->section_header[0].Misc.VirtualSize;
                //代码写入的物理偏移
                mods=entrywrite%16;
                //对齐边界
                if(mods!=0)
                {
                        entrywrite+=(16-mods);
                }
                oldentryaddress=header->opt_head.AddressOfEntryPoint;
                //保存旧的程序入口地址
                newentryaddress=entrywrite+codeoffset;
                //计算新的程序入口地址
                return;
        }
}

void printaddress()
{
        HINSTANCE gLibMsg=NULL;
        DWORD funaddress;
        gLibMsg=LoadLibrary("user32.dll");
        funaddress=(DWORD)GetProcAddress(gLibMsg,"MessageBoxA");
        MessageBoxAadaddress=funaddress;
        gLibMsg=LoadLibrary("kernel32.dll");
        //得到MessageBox在内存中的地址,以便我们使用
}

void writefile()
{
        int ret;
        long retf;
        DWORD address;
        int tmp;
        unsigned char waddress[4]={0};

        ret=_open(filename,_O_RDWR | _O_CREAT | _O_BINARY,_S_IREAD | _S_IWRITE);
        if(!ret)
        {
                printf("error open\n");
                return;
        }

        retf=_lseek(ret,(long)peaddress+40,SEEK_SET);
        //程序的入口地址在PE文件头开始的40处
        if(retf==-1)
        {
                printf("error seek\n");
                return;
        }
        address=newentryaddress;
        tmp=address>>24;
        waddress[3]=tmp;
        tmp=address<<8;
        tmp=tmp>>24;
        waddress[2]=tmp;
        tmp=address<<16;
        tmp=tmp>>24;
        waddress[1]=tmp;
        tmp=address<<24;
        tmp=tmp>>24;
        waddress[0]=tmp;
        retf=_write(ret,waddress,4);
        //把新的入口地址写入文件
        if(retf==-1)
        {
                printf("error write: %d\n",GetLastError());
                return;
        }

        retf=_lseek(ret,(long)entrywrite,SEEK_SET);
        if(retf==-1)
        {
                printf("error seek\n");
                return;
        }
        retf=_write(ret,writeline,18);
        if(retf==-1)
        {
                printf("error write: %d\n",GetLastError());
                return;
        }
        //把writeline写入我们计算出的空间

        retf=_lseek(ret,(long)entrywrite+9,SEEK_SET);
        //更改MessageBox函数地址,它的二进制代码在writeline[10]处
        if(retf==-1)
        {
                printf("error seek\n");
                return;
        }

        address=MessageBoxAadaddress-(progRAV+newentryaddress+9+4);
        //重新计算MessageBox函数的地址,MessageBox函数的原地址减去程序的装载地址加上新的入口地址加9(它的二进制代码相对偏移)加上4(地址长度)
        tmp=address>>24;
        waddress[3]=tmp;
        tmp=address<<8;
        tmp=tmp>>24;
        waddress[2]=tmp;
        tmp=address<<16;
        tmp=tmp>>24;
        waddress[1]=tmp;
        tmp=address<<24;
        tmp=tmp>>24;
        waddress[0]=tmp;
        retf=_write(ret,waddress,4);
        //写入重新计算的MessageBox地址
        if(retf==-1)
        {
                printf("error write: %d\n",GetLastError());
                return;
        }

        retf=_lseek(ret,(long)entrywrite+14,SEEK_SET);
        //更改返回地址,用jpm返回原程序入口地址,其它的二进制代码在writeline[15]处
        if(retf==-1)
        {
                printf("error seek\n");
                return;
        }

        address=0-(newentryaddress-oldentryaddress+4+15);
        //返回地址计算的方法是新的入口地址减去老的入口地址加4(地址长度)加15(二进制代码相对偏移)后取反
        tmp=address>>24;
        waddress[3]=tmp;
        tmp=address<<8;
        tmp=tmp>>24;
        waddress[2]=tmp;
        tmp=address<<16;
        tmp=tmp>>24;
        waddress[1]=tmp;
        tmp=address<<24;
        tmp=tmp>>24;
        waddress[0]=tmp;
        retf=_write(ret,waddress,4);
        //写入返回地址
        if(retf==-1)
        {
                printf("error write: %d\n",GetLastError());
                return;
        }
       
        _close(ret);
        printf("\nall done...\n");
        return;
}

//end

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 246
活跃值: (91)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
error C2065: 'filename' : undeclared identifier

filename 没有定义
2008-9-12 17:03
0
雪    币: 213
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
我知道是filename没有定义,问题是filename如何定义呢?
定义成全局变量的话,用来存储什么呢,他是在一个函数里面使用的,主程序要传入什么参数呢?
2008-9-12 22:18
0
游客
登录 | 注册 方可回帖
返回
//