吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 820|回复: 13
上一主题 下一主题
收起左侧

[已解决] [已经解决]向执行文件exe写入shellcode的疑问(E8计算)

[复制链接]
跳转到指定楼层
楼主
richard_ljd 发表于 2024-9-16 15:26 回帖奖励
本帖最后由 richard_ljd 于 2024-9-17 08:25 编辑

问题解决了
我命名的变量名codebegin把自己迷惑住了,那个只是在FIlebuffer文件状态下的地址,要写入内存状态的地址才行,

因为我自己命名时codebegin,我以为已经算的是Imagebuffer的地址,结果少了一个Imagebase,所以一直有错,函数改了一下就好了

[C++] 纯文本查看 复制代码
1
2
3
4
5
6
//复制CALL,且计算 MESSAGEBOX_WZ - (CALL + 5)实际参数,计算下一句地址需要 - PointerToRawData + VirtualAddress得到内存状态实际地址
int call_s = MESSAGEBOXW_WZ - (pOptionHeader->ImageBase + codebegin + 0xD);            //<------------这里
BYTE c_wz[4];
mitol(call_s, c_wz);
 
memcpy(Shellcode + 0x9, c_wz, 4);




==================================================================================

最近在看教程,老师让用代码的方式自动在程序中写入ShellCode,且能够运行

在手动写入了以后,我也开始了代码写入,先简单来说一下过程

首先程序读入exe文件到FileBuffer,然后进行PE分析,分析完毕以后将FileBuffer转变成ImageBuffer,

随后我将我的ShellCode在这个ImageBuffer中寻找有空闲区域的节(防止自己写入的代码被覆盖),找到以后VirtualAddress + VirtualSize可以到节尾,

[C++] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
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
BYTE Shellcode[] =
{
    0x6A,00,0x6A,00,0x6A,00,0x6A,00,
    0xE8,00,00,00,00,
    0xE9,00,00,00,00
};
int PeHeader::AddShellcode(int Number)
{
 
    int fsize = 0;
 
//遍历节,看是否有可以写入的节区
    for (Number - 1; Number < pPEHeader->NumberOfSections; Number++)
    {
        fsize = (pSectionHeader + Number)->SizeOfRawData - (pSectionHeader + Number)->Misc.VirtualSize;
 
        if (fsize > Shellcode_length)
            break;
 
        if (Number == pPEHeader->NumberOfSections - 1)
            return 0;
    }
 
 
    int codebegin = (pSectionHeader + Number)->VirtualAddress + (pSectionHeader + Number)->Misc.VirtualSize;
 
    //复制CALL,且计算 MESSAGEBOX_WZ - (CALL + 5)实际参数,计算下一句地址需要 - PointerToRawData + VirtualAddress得到内存状态实际地址
    int call_s = MESSAGEBOXW_WZ - (codebegin + 0xE);
    BYTE c_wz[4];
    mitol(call_s, c_wz);
 
    memcpy(Shellcode + 0x9, c_wz, 4);
 
    //复制JMP,且计算 OEP - (JMP + 5)实际参数
    int jmp_s = pOptionHeader->AddressOfEntryPoint - (codebegin + 18);
    BYTE j_wz[4];
    mitol(jmp_s, j_wz);
 
    memcpy(Shellcode + 0xE, j_wz, 4);
 
    //修改OEP,指向添加代码的位置
    BYTE OEP[4];
    mitol((pSectionHeader + Number)->Misc.VirtualSize + (pSectionHeader + Number)->VirtualAddress, OEP);
    memcpy((void*)((DWORD)pNewBuffer + ((DWORD)pOptionHeader - (DWORD)pDosHeader) + 0x10), OEP, 4);
 
    //将计算好的ShellCode写入pNewBuffer
    memcpy((void*)((DWORD)pNewBuffer + codebegin), Shellcode, 18);
 
    return pOptionHeader->AddressOfEntryPoint;
}


然后如上面这个代码段,添加CALL和JMP的地址,修改OEP

代码方面计算基本没有问题(实际有问题,也是这个帖子发出来的原因,不过先继续)

程序跑起来以后,直接运行引发未知错误直接结束,所以我挂上dbg



这个报错提示告诉我:1.指针为空  2.数组越界   3.堆栈溢出    4.内存损坏     5.硬件问题     6.无权限

这六个可能中前5个不好评价,第六个的话也不清楚怎么办(但是应该好歹调试器里面会显示到正确的位置吧)

于是我打算进程序里面看看,跟着jmp走了一会跳进了程序


这边用的是FF15,我尝试改成E8

发现也是可以的,但是回到我的Shellcode就直接炸了,不清楚为什么

下面是完整的代码,能Filebuffer和Imagebuffer相互转换,然后就没什么了()

微云网盘:https://share.weiyun.com/lVcTTb6Q
百度网盘:https://pan.baidu.com/s/1Y4XIVcBEDwEpQE2O9SES_A                  提取码:1234

image.png (171.13 KB, 下载次数: 0)

image.png

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
 楼主| richard_ljd 发表于 2024-9-16 15:43 |楼主
Vvvvvoid 发表于 2024-9-16 15:32
shell code 写成这样试试
[mw_shl_code=asm,true]pushad
push 0

你说的是这种么?裸函数,然后内联汇编,随后直接复制出来就是完整代码

int __declspec(naked) shellcode()
{
    _asm {
        push 0;
        push 0;
        push 0;
        push 0;
        CALL MessageBoxA;
    }
}

int (*p)() = shellcode;

这个虽然是一种办法,但是麻烦的还是E8跳转时Messagebox经过计算的位置才行,如果放在代码内部,这个计算是根据这个函数位置进行计算,我写到其他地方也失效了

如果我理解错了希望能够指出来
推荐
海水很咸 发表于 2024-9-18 18:22
richard_ljd 发表于 2024-9-17 08:03
是很早,早到没法查(),所以这个阶段我想去调用函数都是用dbg进去先查好的用,就像代码里的宏MESSAGEBO ...

仔细看了下 你的代码, 出错的地方 在这里
[C++] 纯文本查看 复制代码
1
2
3
4
5
6
int call_s = MESSAGEBOXW_WZ - (codebegin + 0xE);
 
//运行出错 是因为 实际运行 call_s  -= (模块起始地址 +1);
 
BYTE c_wz[4];
mitol(call_s, c_wz);
你给这个变量加个重定位 让他在运行的时候自己修正。试试
沙发
Vvvvvoid 发表于 2024-9-16 15:32

shell code 写成这样试试
[Asm] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
pushad
push 0
push 0
push 0
push 0
call MessageBoxA
popad
ret
4#
woflant 发表于 2024-9-16 16:45
richard_ljd 发表于 2024-9-16 15:43
你说的是这种么?裸函数,然后内联汇编,随后直接复制出来就是完整代码

int __declspec(naked) shellc ...

楼上的意思是shellcode增加pushad、popad,保存寄存器环境,避免返回到原来汇编处污染寄存器数据
5#
 楼主| richard_ljd 发表于 2024-9-16 18:06 |楼主
woflant 发表于 2024-9-16 16:45
楼上的意思是shellcode增加pushad、popad,保存寄存器环境,避免返回到原来汇编处污染寄存器数据

az,这个东西是把原本oep换成自己的代码,代码跑完就转到原本的oep,不会再回来了,如果硬要说的话得
pushad
push 0
push 0
push 0
push 0
call messagebox
popad
jmp 原oep
代码不会运行回来
messagebox我没记错的话影响的返回值在eax,不会造成什么太大影响,未来写更多东西的时候我注意一下
6#
海水很咸 发表于 2024-9-16 19:12
如果 你在OEP之前运行 会不会 时机太早 ,要自己获取下MessageBoxA 的地址 才行。
7#
zishen 发表于 2024-9-16 22:52
这样确实有隐患问题,想如果是APIHOOK,微软有热补丁前五个字节用来修改,你要是在OEP前执行代码,原本的寄存器的值,还有栈帧被修改,跳转到OEP的时候没有被还原,是这个问题吗?
8#
 楼主| richard_ljd 发表于 2024-9-17 08:03 |楼主
海水很咸 发表于 2024-9-16 19:12
如果 你在OEP之前运行 会不会 时机太早 ,要自己获取下MessageBoxA 的地址 才行。

是很早,早到没法查(),所以这个阶段我想去调用函数都是用dbg进去先查好的用,就像代码里的宏MESSAGEBOX_WZ就是MesssageboxW函数的地址,不过计算是一方面,我自己进到我写入ShellCode的程序,手算填进去也无法找到,这就是我问题的来源()
10#
 楼主| richard_ljd 发表于 2024-9-19 07:30 |楼主
海水很咸 发表于 2024-9-18 18:22
仔细看了下 你的代码, 出错的地方 在这里[mw_shl_code=cpp,true]    int call_s = MESSAGEBOXW_WZ - (co ...

这点我当时调试的时候发现了,已经改正,不过主要问题不是在于这里,问题在于codebegin这个变量本来应该实在Imagebuffer中的地址,但是我没有加入Imagebase,所以一下子地址差了40000,所以出现报错(都跑程序外了,这还不报错),加上以后就好了,你可以看一下我修改了最开始的帖子。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-2-13 15:51

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表