吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 560|回复: 13
收起左侧

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

[复制链接]
richard_ljd 发表于 2024-9-16 15:26
本帖最后由 richard_ljd 于 2024-9-17 08:25 编辑

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

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

[C++] 纯文本查看 复制代码
    //复制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);


image.png

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

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

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

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

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

[C++] 纯文本查看 复制代码

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

image.png

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

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

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


这边用的是FF15,我尝试改成E8
image.png
发现也是可以的,但是回到我的Shellcode就直接炸了,不清楚为什么

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

微云网盘:https://share.weiyun.com/lVcTTb6Q
百度网盘:https://pan.baidu.com/s/1Y4XIVcBEDwEpQE2O9SES_A                  提取码:1234
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++] 纯文本查看 复制代码
    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] 纯文本查看 复制代码
pushad
push 0
push 0
push 0
push 0
call MessageBoxA
popad
ret
woflant 发表于 2024-9-16 16:45
richard_ljd 发表于 2024-9-16 15:43
你说的是这种么?裸函数,然后内联汇编,随后直接复制出来就是完整代码

int __declspec(naked) shellc ...

楼上的意思是shellcode增加pushad、popad,保存寄存器环境,避免返回到原来汇编处污染寄存器数据
 楼主| 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,不会造成什么太大影响,未来写更多东西的时候我注意一下
海水很咸 发表于 2024-9-16 19:12
如果 你在OEP之前运行 会不会 时机太早 ,要自己获取下MessageBoxA 的地址 才行。
zishen 发表于 2024-9-16 22:52
这样确实有隐患问题,想如果是APIHOOK,微软有热补丁前五个字节用来修改,你要是在OEP前执行代码,原本的寄存器的值,还有栈帧被修改,跳转到OEP的时候没有被还原,是这个问题吗?
 楼主| richard_ljd 发表于 2024-9-17 08:03
海水很咸 发表于 2024-9-16 19:12
如果 你在OEP之前运行 会不会 时机太早 ,要自己获取下MessageBoxA 的地址 才行。

是很早,早到没法查(),所以这个阶段我想去调用函数都是用dbg进去先查好的用,就像代码里的宏MESSAGEBOX_WZ就是MesssageboxW函数的地址,不过计算是一方面,我自己进到我写入ShellCode的程序,手算填进去也无法找到,这就是我问题的来源()
 楼主| 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, 2024-11-24 11:45

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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