首页
社区
课程
招聘
[求助]使用代码拉伸程序再压缩后进行存盘,文件打不开以及RVA转FOA的代码问题,望解答谢谢!
2022-1-28 04:53 4159

[求助]使用代码拉伸程序再压缩后进行存盘,文件打不开以及RVA转FOA的代码问题,望解答谢谢!

2022-1-28 04:53
4159

请问各位大佬,我把一个程序从文件状态拉伸后再进行压缩,然后进行存盘,拉伸及压缩的时候内存空间是根据SizeOfImage的大小malloc的,
为何存盘之后软件无法运行.

 

 

D,E是存盘之后的文件,原本的文件是C

 

 

还有一个问题就是,我写了个RVA转FOA的函数,但是测试之后发现,我输入的数据,显示的一直都是在节表的第一个段里,比如我输入RVA=501234 会显示在CODE节里,我再输入RVA=901234,还是显示在CODE节里,通过PE查看,CODE节的长度不可能那么大

 

以下是我的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
#include<iostream>
#include<Windows.h>
#include<stdio.h>
#include<string>
using namespace std;
#define NUMTEST 0
char* pointpath=NULL;
 
 
 
//把文件读取到缓冲区FileBuffer,成功返回开辟的空间的指针,失败返回NULL
LPVOID REPE()
{
    FILE* pfile = NULL;
    DWORD FileSize = 0;
    LPVOID FileBuffer = NULL;
 
    pfile = fopen(pointpath,"rb");
    if (!pfile)
    {
        printf("文件打开失败\n");
        fclose(pfile);
        return NULL;
    }
    fseek(pfile, SEEK_SET, SEEK_END);
    FileSize = ftell(pfile);
    fseek(pfile, SEEK_SET, SEEK_SET);
 
    FileBuffer = malloc(FileSize);
    if (!FileBuffer)
    {
        printf("开辟空间失败\n");
        fclose(pfile);
        free(FileBuffer);
        return NULL;
    }
 
    size_t n = fread(FileBuffer,FileSize,1,pfile);
    if (!n)
    {
        printf("读取文件到内存失败\n");
        free(FileBuffer);
        return NULL;
    }
 
    fclose(pfile);
    return FileBuffer;
}
 
//把FileBuffer 拉伸成ImageBuffer                                                                            //2022/1/26 搞定没问题
LPVOID FileBufferToImageBuffer()
{
    LPVOID ImageBuffer = NULL;
    LPVOID FileBuffer = NULL;
    FileBuffer = REPE();
    if (!FileBuffer)
    {
        printf("FileBuffer赋值成功\n");
        free(FileBuffer);
    }
    if (*(PWORD)((char*)FileBuffer) != IMAGE_DOS_SIGNATURE)
    {
        printf("在FTI里  不是有效的MZ标记\n");
    }
    PIMAGE_DOS_HEADER FILE_DOC = NULL;
    PIMAGE_NT_HEADERS FILE_NT = NULL;
    PIMAGE_FILE_HEADER FILE_FIE = NULL;
    PIMAGE_OPTIONAL_HEADER64 FILE_OP64 = NULL;
    PIMAGE_SECTION_HEADER   FILE_SEC = NULL;
 
    FILE_DOC = (PIMAGE_DOS_HEADER)((char*)FileBuffer);  //头部转化
    FILE_NT = (PIMAGE_NT_HEADERS)((char*)FileBuffer + FILE_DOC->e_lfanew);
    if (FILE_NT->Signature!=IMAGE_NT_SIGNATURE)
    {
        printf("在FTI里   NT头部赋值失败");
    }
    FILE_FIE= (PIMAGE_FILE_HEADER)((char*)FileBuffer + FILE_DOC->e_lfanew+4);
    FILE_OP64=(PIMAGE_OPTIONAL_HEADER64)((char*)FileBuffer + FILE_DOC->e_lfanew + 4+IMAGE_SIZEOF_FILE_HEADER);
    FILE_SEC = (PIMAGE_SECTION_HEADER)((char*)FileBuffer + FILE_DOC->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER + FILE_FIE->SizeOfOptionalHeader);  //第一个节表的位置
    DWORD ImageBufferSize = 0;
    ImageBufferSize = FILE_OP64->SizeOfImage;
    ImageBuffer = malloc(ImageBufferSize);
    if (!ImageBuffer)
    {
        printf("拉伸后的空间失败了\n");
        free(ImageBuffer);
        return NULL;
    }
 
    memset(ImageBuffer, 0, ImageBufferSize);
 
    //开始Copy FileBufferToImageBuffer
    memcpy(ImageBuffer, FileBuffer, FILE_OP64->SizeOfHeaders);  //copy头部
    PIMAGE_DOS_HEADER IMAGE_DOC = NULL;
    PIMAGE_NT_HEADERS IMAGE_NT = NULL;
    PIMAGE_FILE_HEADER IMAGE_FIE = NULL;
    PIMAGE_OPTIONAL_HEADER64 IMAGE_OP64 = NULL;
    PIMAGE_SECTION_HEADER   IMAGE_SEC = NULL;
 
    IMAGE_DOC = (PIMAGE_DOS_HEADER)(ImageBuffer);
    IMAGE_NT = (PIMAGE_NT_HEADERS)((char*)ImageBuffer + IMAGE_DOC->e_lfanew);
    IMAGE_FIE = (PIMAGE_FILE_HEADER)((char*)ImageBuffer + IMAGE_DOC->e_lfanew + 4);
    IMAGE_OP64=(PIMAGE_OPTIONAL_HEADER64)((char*)ImageBuffer + IMAGE_DOC->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER);
    IMAGE_SEC = (PIMAGE_SECTION_HEADER)((char*)ImageBuffer + IMAGE_DOC->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER + IMAGE_FIE->SizeOfOptionalHeader);
 
    int Nsec = FILE_FIE->NumberOfSections;
    cout << "复制的节表的数量=" << Nsec << endl;
    for (int i = 0; i < Nsec; i++)
    {
        FILE_SEC = (PIMAGE_SECTION_HEADER)((char*)FileBuffer + FILE_DOC->e_lfanew
                   + 4 + IMAGE_SIZEOF_FILE_HEADER + FILE_FIE->SizeOfOptionalHeader+i*IMAGE_SIZEOF_SECTION_HEADER);
 
        IMAGE_SEC = (PIMAGE_SECTION_HEADER)((char*)ImageBuffer + IMAGE_DOC->e_lfanew
            + 4 + IMAGE_SIZEOF_FILE_HEADER + IMAGE_FIE->SizeOfOptionalHeader + i * IMAGE_SIZEOF_SECTION_HEADER);
 
        //关于memcpy的函数我们要注意到参数的传递方向(目标,源头,复制的长度)
        memcpy((PDWORD)((char*)ImageBuffer+(FILE_SEC->PointerToRawData)), (PDWORD)((char*)FileBuffer + (IMAGE_SEC->VirtualAddress)),FILE_SEC->SizeOfRawData);  //通过循环把节的数据拷贝
        printf("从FileBuffer节表%s复制到ImageBuffer节表%s成功\n", FILE_SEC->Name, IMAGE_SEC->Name);
    }
 
    printf("FileBufferToImageBuffer结束,ImageBuffer的尺寸:%x\n",IMAGE_OP64->SizeOfImage);
    return ImageBuffer;
}
 
 
//把ImageBuffer 拉伸成NewBuffer,需要传入ImageBuffer空间的指针,成功返回NewBuffer的空间地址指针               //2022/1/26 搞定没问题
LPVOID ImageBufferToNewBuffer(LPVOID ImageBuffer)
{
    LPVOID NewBuffer = NULL;
    PIMAGE_DOS_HEADER IMAGE_DOC = NULL;
    PIMAGE_NT_HEADERS IMAGE_NT = NULL;
    PIMAGE_FILE_HEADER IMAGE_FILE = NULL;
    PIMAGE_OPTIONAL_HEADER64 IMAGE_OP64 = NULL;
    PIMAGE_SECTION_HEADER IMAGE_SEC = NULL;
 
    IMAGE_DOC =(PIMAGE_DOS_HEADER)ImageBuffer;
    if (IMAGE_DOC->e_magic != IMAGE_DOS_SIGNATURE)
    {
        printf("在ITNew里 不是有效的MZ标记\n");
        free(ImageBuffer);
    }
 
    IMAGE_NT = (PIMAGE_NT_HEADERS)((char*)ImageBuffer + IMAGE_DOC->e_lfanew);
    if (IMAGE_NT->Signature != IMAGE_NT_SIGNATURE)
    {
        printf("在ITNew里   NT头部赋值失败");
    }
    IMAGE_FILE = (PIMAGE_FILE_HEADER)((char*)ImageBuffer + IMAGE_DOC->e_lfanew + 4);
    IMAGE_OP64 = (PIMAGE_OPTIONAL_HEADER64)((char*)ImageBuffer + IMAGE_DOC->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER);
    IMAGE_SEC = (PIMAGE_SECTION_HEADER)((char*)ImageBuffer + IMAGE_DOC->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER + IMAGE_FILE->SizeOfOptionalHeader);
 
    DWORD NewBufferSize = 0;
    NewBufferSize = IMAGE_OP64->SizeOfImage;
    NewBuffer = malloc(NewBufferSize);
    if (!NewBuffer)
    {
        printf("NewBuffer空间开辟失败\n");
        free(NewBuffer);
    }
 
    memset(NewBuffer, 0, NewBufferSize);
    //开始ImageBuffer 转化为NewBuffer
 
    memcpy(NewBuffer, ImageBuffer, IMAGE_OP64->SizeOfHeaders);  //copy头部
 
    PIMAGE_DOS_HEADER New_DOC = NULL;
    PIMAGE_NT_HEADERS New_NT = NULL;
    PIMAGE_FILE_HEADER New_FIE = NULL;
    PIMAGE_OPTIONAL_HEADER64 New_OP64 = NULL;
    PIMAGE_SECTION_HEADER   New_SEC = NULL;
 
    New_DOC = (PIMAGE_DOS_HEADER)(NewBuffer);
    New_NT = (PIMAGE_NT_HEADERS)((char*)NewBuffer + New_DOC->e_lfanew);
    New_FIE = (PIMAGE_FILE_HEADER)((char*)NewBuffer + New_DOC->e_lfanew + 4);
    New_OP64 = (PIMAGE_OPTIONAL_HEADER64)((char*)NewBuffer + New_DOC->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER);
    New_SEC = (PIMAGE_SECTION_HEADER)((char*)NewBuffer + New_DOC->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER + New_FIE->SizeOfOptionalHeader);
 
    int Nsec = New_FIE->NumberOfSections;
    for (int i = 0; i < Nsec; i++)
    {
        IMAGE_SEC = (PIMAGE_SECTION_HEADER)((char*)ImageBuffer + IMAGE_DOC->e_lfanew
            + 4 + IMAGE_SIZEOF_FILE_HEADER + IMAGE_FILE->SizeOfOptionalHeader + i * IMAGE_SIZEOF_SECTION_HEADER);
 
        New_SEC = (PIMAGE_SECTION_HEADER)((char*)NewBuffer + New_DOC->e_lfanew
            + 4 + IMAGE_SIZEOF_FILE_HEADER + New_FIE->SizeOfOptionalHeader + i * IMAGE_SIZEOF_SECTION_HEADER);
 
        memcpy(((PWORD)(char*)NewBuffer + (New_SEC->PointerToRawData)), ((PWORD)(char*)ImageBuffer + (IMAGE_SEC->VirtualAddress)), New_SEC->SizeOfRawData);
        //memcpy((PDWORD)((char*)FileBuffer + (IMAGE_SEC->VirtualAddress)), (PDWORD)((char*)ImageBuffer + (FILE_SEC->PointerToRawData)), FILE_SEC->SizeOfRawData);  //通过循环把节的数据拷贝
    }
 
    printf("ImageBufferToNewBuffer结束,Newbuffer的尺寸是:%x\n",New_OP64->SizeOfImage);
    return NewBuffer;
}
 
 
//存盘用函数,传入的参数是内存映像空间的指针 buffer                                                         //2022/1/26 搞定没问题,但是存盘之后打不开
VOID FileSave(LPVOID Buffer)
{
    char* FileSavepath= NULL;
    string Filesavepath;
    cout << "请输入要存盘的文件路径" << endl;
    cin >> Filesavepath;
    FileSavepath = &Filesavepath[0];
    cout << "文件的路径为:" << FileSavepath << endl;
 
    DWORD SaveSize=0;
    cout << "请输入存盘的函数尺寸(buffer函数有显示)" << endl;
    cin >> SaveSize;
    cout << "存盘尺寸为:" << SaveSize << endl;
 
    FILE* FileSave = NULL;
    FileSave = fopen(FileSavepath, "wb");
    if (!FileSave)
    {
        printf("新建流文件失败\n");
        fclose(FileSave);
    }
 
    size_t saven= fwrite(Buffer, SaveSize,1,FileSave);
    if (!saven)
    {
        printf("fwrite写入函数失败\n");
        fclose(FileSave);
    }
    else
    {
        printf("写入成功\n");
    }
}
 
 
 
 
int main()
{
    string path;                                 
    cout << "请输入文件的路径及名称" << endl;
    cin >> path;
    cout << "输入结束,路径为:" <<path<< endl;
    pointpath = &path[0];
    LPVOID imagebuffers = FileBufferToImageBuffer();
    printf("拉伸后的内存地址是%x\n", imagebuffers);
    LPVOID newbuffers = ImageBufferToNewBuffer(imagebuffers);
    printf("压缩后的内存地址是%x\n", newbuffers);
    cout << "开始将Newbuffer的代码进行存盘" << endl;
    FileSave(newbuffers);
 
 
}

另外这个是RVA转FOA的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//输入数据,会根据你一开始输入的文件路径进行判断                                                           
VOID RvaToFoa(DWORD Number)
{
    LPVOID rvatofoa = NULL;
    rvatofoa= REPE();   //buffer的指针
 
    PIMAGE_DOS_HEADER RTF_DOC = NULL;
    PIMAGE_NT_HEADERS RTF_NT = NULL;
    PIMAGE_FILE_HEADER RTF_FIE = NULL;
    PIMAGE_OPTIONAL_HEADER64 RTF_OP64 = NULL;
    PIMAGE_SECTION_HEADER   RTF_SEC = NULL;
 
    RTF_DOC = (PIMAGE_DOS_HEADER)rvatofoa;
    RTF_NT = (PIMAGE_NT_HEADERS)((char*)rvatofoa + RTF_DOC->e_lfanew);
    RTF_FIE = (PIMAGE_FILE_HEADER)((char*)rvatofoa + RTF_DOC->e_lfanew+4);
    RTF_OP64 = (PIMAGE_OPTIONAL_HEADER64)((char*)rvatofoa + RTF_DOC->e_lfanew+4+ IMAGE_SIZEOF_FILE_HEADER);
    //RTF_SEC = (PIMAGE_SECTION_HEADER)((char*)rvatofoa + RTF_DOC->e_lfanew +4+ IMAGE_SIZEOF_FILE_HEADER + RTF_FIE->SizeOfOptionalHeader);  //节表
 
    cout << "你输入的RVA数据是" << Number << endl;
 
    DWORD FOA = 0;
 
    int NumberofSection = RTF_FIE->NumberOfSections;
 
    //草!!一直都是CODE段
 
 
    if (Number < RTF_OP64->SizeOfHeaders)
    {
        FOA = Number;
        cout << "RVA的数据不在节表中,在前面的头里面" << endl;
        cout << "FOA=" << FOA << endl;
    }
    for (int i = 0; i < NumberofSection; i++)
    {
            RTF_SEC = (PIMAGE_SECTION_HEADER)((char*)rvatofoa + RTF_DOC->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER + RTF_FIE->SizeOfOptionalHeader + i * IMAGE_SIZEOF_SECTION_HEADER);
            if ((Number > RTF_SEC->VirtualAddress) && (Number <RTF_SEC->VirtualAddress + RTF_SEC->Misc.VirtualSize));
            {
                printf("位于节%s\n", RTF_SEC->Name);
                FOA = Number - RTF_SEC->VirtualAddress + RTF_SEC->PointerToRawData;
                cout << "FOA=" << FOA << endl;
                RTF_SEC = (PIMAGE_SECTION_HEADER)(RTF_OP64 + RTF_FIE->SizeOfOptionalHeader + 0 * IMAGE_SIZEOF_SECTION_HEADER);
                break;
             }
    }
 
}
 
 
int main()
{
    string path;                                 
    cout << "请输入文件的路径及名称" << endl;
    cin >> path;
    cout << "输入结束,路径为:" <<path<< endl;
    pointpath = &path[0];
    cout << "请输入RVA的数据" << endl;
    DWORD Numb = 0;
    cin >>Numb ;
    RvaToFoa(Numb);
    return 0;
}

[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

收藏
点赞0
打赏
分享
最新回复 (6)
雪    币: 13383
活跃值: (4723)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tDasm 2022-1-28 09:13
2
1
1、重定位处理了吗?
2、拉伸再压缩?那么运行时你要写个壳,在壳中解压再还原,之后跳转到原OEP正常运行。
雪    币: 159
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
白嫖怪 2022-1-28 10:01
3
0
谢谢大佬,我重定位表还没有处理,我还有一个问题就是拉伸的时候申请的空间是根据程序的SizeofImage申请的,我不理解帖子里第二张图片的结果,原本的文件是12KB,我用SizeofImage申请后存盘的程序文件为何才8KB..希望大佬解答下,谢谢(∩_∩)
雪    币: 13383
活跃值: (4723)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tDasm 2022-1-28 10:29
4
1
SizeofImage 加载到内存的虚拟空间大小。
你应该按照节表分别处理(raw data offs和 raw data size,用每节的文件偏移和大小,这个决定文件大小)。
雪    币: 159
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
白嫖怪 2022-1-28 11:45
5
0
tDasm SizeofImage 加载到内存的虚拟空间大小。 你应该按照节表分别处理(raw data offs和 raw data size,用每节的文件偏移和大小,这个决定文件大小)。
明白了大佬,非常感谢你O(∩_∩)O
雪    币: 159
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
白嫖怪 2022-2-4 04:17
6
0
tDasm SizeofImage 加载到内存的虚拟空间大小。 你应该按照节表分别处理(raw data offs和 raw data size,用每节的文件偏移和大小,这个决定文件大小)。
不好意思大佬.我试着几天越解决越混乱.按照滴水教程里老师说的Newbuffer的大小是用最后一个节在文件中的偏移+这个节的大小,而在网上找的代码他们用的都是用每个节表的大小+SizeofHanders来决定要申请的Newbuffer的节的大小.但是两种方式得到的数据都比PEtool里打开的文件的尺寸还小。另外就是我代码内存拷贝跟网上的没差,但是存盘的文件用Winhex打开发现还是按照内存对齐的方式存的,而且少了很多的节。。
雪    币: 159
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
白嫖怪 2022-2-4 04:24
7
0

左边的是源文件,用WINHEX打开文件的时候存的是600,右边则是我拉伸后压缩的,同样的节在文件中的位置却是1000


另外就是存盘之后还少了很多的节....请大佬救我


核心代码

NewBuffer = malloc(NewBufferSize);
	if (!NewBuffer)
	{
		printf("NewBuffer空间开辟失败\n");
		free(NewBuffer);
	}

	memset(NewBuffer, 0, NewBufferSize);
	//开始ImageBuffer 转化为NewBuffer

	memcpy(NewBuffer, ImageBuffer, IMAGE_OP64->SizeOfHeaders);  //copy头,将ImageBuffer的所有头Copy到NewBuffer里

	PIMAGE_DOS_HEADER New_DOC = NULL;
	PIMAGE_NT_HEADERS New_NT = NULL;
	PIMAGE_FILE_HEADER New_FIE = NULL;
	PIMAGE_OPTIONAL_HEADER64 New_OP64 = NULL;
	PIMAGE_SECTION_HEADER   New_SEC = NULL;
	New_DOC = (PIMAGE_DOS_HEADER)(NewBuffer);
	New_NT = (PIMAGE_NT_HEADERS)((char*)NewBuffer + New_DOC->e_lfanew);
	New_FIE = (PIMAGE_FILE_HEADER)((char*)NewBuffer + New_DOC->e_lfanew + 4);
	New_OP64 = (PIMAGE_OPTIONAL_HEADER64)((char*)NewBuffer + New_DOC->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER);
	New_SEC = (PIMAGE_SECTION_HEADER)((char*)NewBuffer + New_DOC->e_lfanew 
	+ 4 + IMAGE_SIZEOF_FILE_HEADER + New_FIE->SizeOfOptionalHeader);

	
	
	int Nsec = New_FIE->NumberOfSections;
	cout << "要复制的节的数量=" << Nsec << endl;


	//Imagebuffer源节
	IMAGE_SEC = (PIMAGE_SECTION_HEADER)((char*)ImageBuffer + IMAGE_DOC->e_lfanew
		+ 4 + IMAGE_SIZEOF_FILE_HEADER + IMAGE_FILE->SizeOfOptionalHeader);
	//Newbuffer 目标节
	New_SEC = (PIMAGE_SECTION_HEADER)((char*)NewBuffer + New_DOC->e_lfanew
		+ 4 + IMAGE_SIZEOF_FILE_HEADER + New_FIE->SizeOfOptionalHeader);
	for (int i = 0; i < Nsec; i++)
	{
	
	
//核心代码
		printf("目标Newbuffer第%x节:%s的文件地址是%x\n", i+1, New_SEC[i].Name, New_SEC[i].PointerToRawData);
		memcpy(((char*)NewBuffer + (New_SEC[i].PointerToRawData)), ((char*)ImageBuffer 
		+ (IMAGE_SEC[i].VirtualAddress)), New_SEC[i].SizeOfRawData);
		
	}

	cout << "ImageBufferToNewBuffer结束,Newbuffer的尺寸是:" << NewBufferSize << endl;
	return NewBuffer;


游客
登录 | 注册 方可回帖
返回