小编Ell*_*ink的帖子

绕行和GCC内联汇编(Linux)

我正在为一个为(我们)modders提供API的游戏编程扩展.这个API提供了各种各样的东西,但它有一个限制.API仅用于"引擎",这意味着基于引擎发布的所有修改(mod)都不提供/具有任何类型的(特定于mod)API.我创建了一个'签名扫描程序'(注意:我的插件是作为共享库加载的,用-share&-fPIC编译),它找到了感兴趣的函数(这很简单,因为我在linux上).所以要解释一下,我将采取一个具体的案例:我已经找到了一个感兴趣的函数的地址,它的函数头很简单int * InstallRules(void);.它不需要任何东西(void)并返回一个整数指针(对我感兴趣的对象).现在,我想要做的是创建一个绕行(并记住我有函数的起始地址),对我自己的函数,我想表现如下:

void MyInstallRules(void)
{
    if(PreHook() == block) // <-- First a 'pre' hook which can block the function
        return;
    int * val = InstallRules(); // <-- Call original function
    PostHook(val); // <-- Call post hook, if interest of original functions return value
}
Run Code Online (Sandbox Code Playgroud)

现在这是交易; 我没有任何关于功能挂钩的经验,而且我对内联汇编(仅限AT&T)知之甚少.互联网上预先制作的绕行程序包适用于Windows或使用其他整个方法(即预加载dll以覆盖原始程序).所以基本上; 我该怎么办才能走上正轨?我应该阅读有关调用约定(在本例中为cdecl)并了解内联汇编或该怎么做?最好的可能是linux绕行的功能性封装类.最后,我想要一些简单的事情:

void * addressToFunction = SigScanner.FindBySig("Signature_ASfs&43"); // I've already done this part
void * original = PatchFunc(addressToFunction, addressToNewFunction); // This replaces the original function with a hook to mine, …
Run Code Online (Sandbox Code Playgroud)

linux assembly hook gcc detours

8
推荐指数
1
解决办法
1468
查看次数

使用C++与程序集在运行时分配和创建新函数

我一直在研究一个(C++)项目,它需要完全动态分配的函数,这意味着malloc/new和mprotect,然后手动修改缓冲区到汇编代码.因此我完全想知道,我的这个"缓冲区"需要什么,因为它是任何其他_cdecl函数的复制品.例如:

int ImAcDeclFunc(int a, int b)
{
     return a + b;
}
Run Code Online (Sandbox Code Playgroud)

如果我想从字面上创建这个函数的副本,但是完全动态,那需要什么(并记住它是带有内联汇编的C++ )?对于初学者,我想我必须做这样的事情(或类似的解决方案):

// My main....
byte * ImAcDeclFunc = new byte[memory];
mprotect(Align(ImAcDeclFunc), pageSize, PROT_EXEC | PROT_READ | PROT_WRITE);
Run Code Online (Sandbox Code Playgroud)

在此之后我将不得不找出汇编代码ImAcDeclFunc(int a, int b);.现在我在组装时仍然很糟糕,那么这个函数将如何用于AT&T语法?这是我的大胆尝试:

push %ebp
movl %%ebp, %%esp
movl 8(%ebp), %%eax
movl 12(%ebp), %%edx
addl edx, eax
pop ebp
ret
Run Code Online (Sandbox Code Playgroud)

现在如果这段代码是正确的(我非常怀疑,请纠正我)我只需要在十六进制中找到这个代码的值(例如,'jmp'是0xE9而'inc'是0xFE),并直接使用这些值C++?如果我继续以前的C++代码:

*ImAcDeclFunc = 'hex value for push'; // This is 'push' from the first line
*(uint)(ImAcDeclFunc + 1) = 'address to …
Run Code Online (Sandbox Code Playgroud)

c++ gcc inline-assembly att dynamic-function

7
推荐指数
1
解决办法
2201
查看次数

可变参数的汇编中的有效模式

我认为我的问题可能看起来有点奇怪,但在这里; 我正在尝试用C++动态创建一个程序(主要是为了它的乐趣,但也是出于编程原因)并且它并不像听起来那么难.要做到这一点,你必须在运行时使用程序集,如下所示:

byte * buffer = new byte[5];
*buffer = '0xE9'; // Code for 'jmp'
*(uint*)(buffer + 1) = 'address destination'; // Address to jump to
Run Code Online (Sandbox Code Playgroud)

这比看起来容易得多,因为我只针对一个平台和编译器; 使用Linux 32位的GCC(也只有一个调用约定,cdecl).所以我试图创建一个动态汇编函数来重定向来自触发器的调用,所以我可以使用类方法作为回调(即使使用C API库(当然还有cdecl)).我只需要它来支持指针和本机类型(char,int,short等......).

ANYTHING MyRedirect(ANY AMOUNT ARGUMENTS)
{
    return MyClassFunc('this', ANY AMOUNT ARGUMENTS);
}
Run Code Online (Sandbox Code Playgroud)

上面的函数是我想要在纯汇编中创建的函数(在内存中使用C++).由于函数非常简单,因此ASM也很简单(取决于参数).

55                      push   %ebp
89 e5                   mov    %esp,%ebp
83 ec 04                sub    $0x4,%esp
8b 45 08                mov    0x8(%ebp),%eax
89 04 24                mov    %eax,(%esp)
e8 00 00 00 00          call   <address>
c9                      leave
c3                      ret  
Run Code Online (Sandbox Code Playgroud)

所以在我的程序中,我创建了一个ASM模式生成器(因为我不太了解ASM,我搜索模式).此函数可以通过指定函数所需的参数量来生成汇编代码(以字节为单位,对于上面的确切情况,即重定向和返回的函数).这是我的C++代码的片段.

std::vector<byte> detourFunc(10 …
Run Code Online (Sandbox Code Playgroud)

c++ linux assembly gcc 32-bit

7
推荐指数
1
解决办法
815
查看次数

C++和FULLY动态函数

我有一个绕道而行的问题.众所周知,Detours只能在5个字节的空间中移动(即'jmp'调用和4字节地址).因此,不可能在类(方法)中使用'hook'函数,你不能提供'this'指针,因为没有足够的空间(这里的问题得到了更彻底的解释).所以我整天都在集思广益寻找解决方案,现在我想要你对这个主题的想法,所以我不会在不知道是否可能的情况下开始3-5天的项目.

我最初有3个目标,我希望'hook'函数是类方法,我希望整个方法是面向对象的(没有静态函数或全局对象),而最坏/最难的部分是完全动态的.这是我的(理论上)解决方案; 使用程序集可以在运行时修改函数(一个完美的例子是任何绕行方法).因为我可以动态修改函数,我不应该也能动态创建它们吗?例如; 我分配内存,比方说~30个字节(通过malloc/new).是不是可以用对应于不同汇编运算符的二进制数替换所有字节(如0xE9是'jmp')然后直接调用地址(因为它将包含一个函数)?

注意:我事先知道返回值,以及我想要绕道的所有函数的所有参数,并且因为我使用GCC,所以thiscall约定实际上与_cdecl约定相同.

所以这是我的想法/即将实施; 我创建了一个'Function'类.此构造函数采用可变量的参数(第一个参数除外,它描述了目标函数的返回值).

每个参数都是钩子将接收的参数的描述(大小,以及它是否是指针).所以我想说我想为一个创建一个Function类int * RandomClass::IntCheckNum(short arg1);.然后我就必须这样做:Function func(Type(4, true), Type(4, true), Type(2, false));.其中'类型'定义为Type(uint size, bool pointer).然后通过程序集我可以动态创建函数(注意:这将全部使用_cdecl调用约定),因为我可以计算参数的数量和总大小.

编辑:对于示例,Type(4, true)是返回值(int*),scond Type(4, true)是RandomClass'this'指针并Type(2, false)描述第一个参数(简短arg1).

通过这个实现,我可以很容易地将类方法作为回调,但是它需要大量的汇编代码(我甚至没有特别经验).最后,唯一非动态的东西就是我的回调类中的方法(也需要前后回调).

所以我想知道; 这可能吗?它需要多少工作,我是否在这里?

编辑:我很抱歉,如果我把所有东西都弄得有些模糊,但是如果你想要更全面的解释,请问!

EDIT2:我还想知道,如果我能在某处找到所有汇编运算符的十六进制值?一份清单会有所帮助!和/或如果有可能以某种方式"保存"asm(""); 代码在内存地址(我非常怀疑).

c++ assembly detours this cdecl

6
推荐指数
1
解决办法
859
查看次数

可变参数模板:迭代类型/模板参数

我最近一直在使用libffi,因为它使用了C API,所以任何抽象都是通过使用void指针(好的'C')来完成的.我正在创建一个使用此API的类(具有可变参数模板).类声明如下:(其中Ret=返回值和Args=函数参数)

template <typename Ret, typename... Args>
class Function
Run Code Online (Sandbox Code Playgroud)

在这个类中,我还声明了两个不同的函数(简化):

Ret Call(Args... args); // Calls the wrapped function
void CallbackBind(Ret * ret, void * args[]); // The libffi callback function (it's actually static...)
Run Code Online (Sandbox Code Playgroud)

我希望能够使用CallCallbackBind; 那是我的问题.我不知道我应该如何将void*数组转换为模板化参数列表.这就是我想要的或多或少:

CallbackBind(Ret * ret, void * args[])
{
 // I want to somehow expand the array of void pointers and convert each
 // one of them to the corresponding template type/argument. The length
 // …
Run Code Online (Sandbox Code Playgroud)

c++ linux g++ libffi c++11

6
推荐指数
1
解决办法
5606
查看次数

在编译时键入specialized

我正在写一个与其共享几个不同特征std::function的类(或者至少类在很多方面类似).众所周知std::function,通过指定模板参数(即std::function<void (std::string&)>)来实例化,对于我的类来说它是相同的.我有一个例外,不过,我想专攻一个单一的在我的类函数,如果返回值是无效的(std::function<"return value" ("parameters">).我需要在编译时完成这项工作,而我无法让它按预期工作.以下是一些测试代码供您解释:

#include <iostream>
#include <type_traits>

template <typename T> class Test { };

template <typename Ret, typename... Args>
class Test<Ret (Args...)>
{
public:
    Ret operator()(Args...)
    {
        if(std::is_void<Ret>::value)
        {
             // Do something...
        }

        else /* Not a void function */
        {
            Ret returnVal;
            return returnVal;
        }
    }
};

int main(int argc, char * argv[])
{
    Test<void (char)> test;
    test('k');
}
Run Code Online (Sandbox Code Playgroud)

正如您可以清楚地看到的,如果编译器在上面的测试中没有删除'else'分支,我的代码将尝试创建一个void值(即void returnVal;).问题是编译器没有删除分支,所以我最终得到一个编译器错误:

./test.cpp:在'Ret Test :: operator()(Args ...)的实例化中[含Ret …

c++ linux gcc templates c++11

6
推荐指数
1
解决办法
1974
查看次数

使用共享库公开类型安全的动态API

我正在为应用程序编写插件API接口.插件在运行时作为共享库加载.他们可以通过界面访问应用程序API,例如:

class IPluginAPI
{
public:
 virtual bool IsPluginsLoaded(void) = 0;
 virtual bool IsHookingEnabled(void) = 0;
 // And about 50 more methods
};
Run Code Online (Sandbox Code Playgroud)

插件可以请求"监听"某些事件(例如MouseClick,MouseScroll等等).这些功能共计300多个不同的事件.通常我会做这样的事情:

extern "C" void SetEventHooks(APITable& table)
{
 table.MouseClick = &PluginMouseClickEvent;
 table.MouseMove = &PluginMouseMoveEvent;
}
Run Code Online (Sandbox Code Playgroud)

虽然SetEventHooks函数驻留在插件库中并且从应用程序调用,但插件可以通过指向其函数来监听感兴趣的函数.这不是我想要使用的方法,但我想提供某种抽象.这就是我的想法:

// Interface IPluginAPI supplies a 'SetEventHook` method such as
void SetEventHook(HookID id, void * callback);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,HookID是一个包含所有函数ID的强类型枚举:

enum class HookID
{
 MouseClick,
 MouseMove,
 // ...
};
Run Code Online (Sandbox Code Playgroud)

所以插件会使用这个函数来监听事件:

pluginAPI->SetEventHook(ID::MouseClick, &myCallback);
Run Code Online (Sandbox Code Playgroud)

这种方法的问题在于它不是类型安全的,我不能直接使用模板(因为这在运行时作为库完成).我不想为每个事件公开300个不同的功能(例如SetHookMouseMove(void (*)(int, int)),依此类推).我的最后一个想法是,插件有一个实用程序模板函数,使这种类型安全,但我不知道如何以一种简单的方式实现它(并且没有样板代码):

template <typename …
Run Code Online (Sandbox Code Playgroud)

c++ gcc shared-libraries c++11

5
推荐指数
1
解决办法
645
查看次数

静态链接SQLite和DMD(Windows x86)

我试图静态链接sqlite3但没有成功.我正在使用'etc.c.sqlite3'标题和sqlite3合并.为了创建.lib文件,我尝试了VC++和MinGW-gcc,这两个文件都成功编译了源文件 - 但它们都生成COFF对象格式(optlink,DMD使用,与OMF一起使用).在阅读了'digitalmars.D'上的大量帖子后,我尝试了几种不同的解决方案.

objconv:

  • 试图转换用GCC创建的lib文件,导致未定义的符号,如__divdi3和__muldi3,无法解决这个问题.

  • 还尝试将sqlite3.o文件转换为*.obj,然后使用digitalmars'lib.exe' - 也不成功

  • 在VC++生成的lib上尝试objconv失败,原因是:"SQLite.lib是一个导入库"

IMPLIB:

  • 如果我从sqlite.org下载预编译的DLL并使用implib,它会生成一个lib文件,但名称mangling似乎不匹配,因为即使我链接到静态库,我仍然会收到相同的sqlite错误(例如undefined符号_sqlite3_open,_sqlite3_errmsg,_sqlite3_close...

coffimplib:

  • 如果我在VC++创建的库文件上使用coffimplib,程序会生成一个几乎为空的文件(~2KB),它只包含垃圾(即根本没有符号,大多数只是'null'值).

  • 如果我对GCC创建的库执行相同操作,coffimplib会抱怨"不是导入库",并且不会生成转换后的库文件.

如果我使用DMC编译sqlite3合并,则编译失败会抱怨大量错误.所以我在这里,无处可去,有没有人有任何想法或提示可以解决这个问题?

注意:我不想使用DLL,但静态链接sqlite(对于可执行文件大小的问题).

windows sqlite d dmd

5
推荐指数
1
解决办法
929
查看次数

std :: function的奇怪行为

我正在使用C++ 11库中的标准函数包装器,我看到它的布尔运算符有一些奇怪的行为.如果我创建一个std::function对象,则布尔运算符返回false.如果我分配nullptr给对象并再次检查,则仍然如此.当我为它分配一个我已经转换为函数指针的void指针时出现问题.考虑以下程序:

#include <functional>
#include <iostream>

void* Test() {
    return nullptr;
}

int main(int argc, char* argv[]) {
    std::function<void()> foo;
    std::cout << !!foo << std::endl;

    foo = nullptr;
    std::cout << !!foo << std::endl;

    foo = reinterpret_cast<void(*)()>(Test());
    std::cout << !!foo << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我期望作为输出,0 0 0但结果是0 0 1(见演示).任何人都可以解释为什么布尔运算符在包含空的,不可调用的函数指针时返回true?并请还提到的解决方法,检查nullptrstd::function

注意:我已经尝试检查目标是否为null(with foo.target<void*>() == nullptr)而不是使用布尔运算符,但似乎无论函数对象包含什么,目标始终为null(即使函数对象完全没有问题)被称为).

c++ c++11 std-function

4
推荐指数
1
解决办法
501
查看次数

Qt:QMainWindow带有关闭,最小化和帮助按钮

如果我有一个继承QMainWindow的类,我希望它只有按钮; 在窗口栏关闭,最小化和帮助,我该怎么办?

如果我将此代码用于窗口标志: setWindowFlags(Qt::Window | Qt::WindowContextHelpButtonHint | Qt::WindowMinimizeButtonHint); 它会生成一个窗口,其中包含最大化,最小化和关闭按钮.

如果我排除"WindowMinimizeButtonHint",则只有一个帮助和关闭按钮.

如果可能的话,我怎么能这样只有一个关闭,帮助和最小化按钮?

c++ windows qt

3
推荐指数
1
解决办法
2824
查看次数