- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
当人们 Hook 一个函数时,他们通常会用分支指令修改他们想要 Hook 的函数的前几条指令到他们想做一些事情的地方,然后分支回到原来的函数并恢复它,问题在于从字面上看,没有什么是安全的。您试图隐藏的任何值都可以很容易地找到(这些值可以通过许多其他方式找到,而不仅仅是函数 Hook ,但这就是我在这个问题中关注的全部内容)
假设您在 C++ 应用程序中实现了像 MD5 这样的哈希算法(我没有,这只是问题的一个示例),只是为了这个示例假设您有一个 MD5 函数像这样
void GENERATEMD5(const char *plain, char *out);
你会这样调用它
char hashResult[33] = { 0 };//32 + 1 because of null terminator
GENERATEMD5(passwordInputBuffer, hashResult);
memset(passwordInputBuffer, 0, 32);//set password buf back to null
任何人都可以轻松地 Hook 此 GERERATEMD5()
函数,并在传递给该函数时简单地打印出参数。示例
void md5FuncHook(const char *plain, char *out)
{
md5Hook(plain, out);
console::print("Plain: %s - Hash: %s", plain, out);
}
我在考虑这个问题,但我只能想出一种方法来检测一个函数是否被 Hook (假设他们通过修改函数的前几条指令来 Hook 该函数)。那将是检查函数的前几个字节,然后确认它们是它们应该是的。例如,如果我们知道函数 GERERATEMD5()
的前几个字节是
int GERERATEMD5_Function_bytes_0 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_1 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_2 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_3 = 0x12341234;//just random bytes for the example
然后我们可以做这样的事情
void checkIfGENERATEMD5HasBeenHooked()
{
int GERERATEMD5_Function_bytes_0 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_1 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_2 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_3 = 0x12341234;//just random bytes for the example
int readGENERATEMD5FunctionBytes0, readGENERATEMD5FunctionBytes1, readGENERATEMD5FunctionBytes2, readGENERATEMD5FunctionBytes3;
memcpy(&readGENERATEMD5FunctionBytes0, (char *)(&GENERATEMD5 + 0x00), 0x04);
memcpy(&readGENERATEMD5FunctionBytes1, (char *)(&GENERATEMD5 + 0x04), 0x04);
memcpy(&readGENERATEMD5FunctionBytes2, (char *)(&GENERATEMD5 + 0x08), 0x04);
memcpy(&readGENERATEMD5FunctionBytes3, (char *)(&GENERATEMD5 + 0x0C), 0x04);
if(GERERATEMD5_Function_bytes_0 == readGENERATEMD5FunctionBytes0 && GENERATEMD5_Function_bytes_1 == readGENERATEMD5FunctionBytes1 && GENERATEMD5_Function_bytes_2 == readGENERATEMD5FunctionBytes2 && GENERATEMD5_Function_bytes_3 == readGENERATEMD5FunctionBytes3)
{
//our GENERATEMD5() function is clean
}
else
{
//hook detected or some other form of function modification detected
}
}
但是我尝试过的所有方法似乎都行不通。我假设的问题来自于我读取函数本身字节的位置,例如对 memcpy 的调用实际上并未读取位于 &GENERATEMD5 + OFFSET
的字节。我只是做错了什么吗?还是有更好/不同的方式来做我想完成的事情? (顺便说一句,是的,我知道攻击者在 Hook 您的函数时可能会使用许多其他 Hook 方法,除了我上面描述的方法之外,还有许多其他方法可以从您的可执行文件中获取您的敏感信息,但这个问题有与这些无关,所以请只关注问题,而不是仅仅说“这样做毫无意义”或“有简单的方法可以绕过它”等...)
最佳答案
我已经做到了。问题是加载程序会在重定位期间修改代码,因此您不能依赖操作数字段每次都是相同的值。在我的例子中,我使用了反汇编库并仅对操作码字节进行了哈希处理。我使用 BASTARD 在运行时进行反汇编,但该项目早就死了。我认为现在有更好的选择。
原则上,您可能会以不会发生重定位修正的方式编写目标函数,但这会带来更多的麻烦,而不是值得的。
关于C++ 检测函数是否被 Hook (32 位机器),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49277363/
我有一个 if 语句,如下所示 if (not(fullpath.lower().endswith(".pdf")) or not (fullpath.lower().endswith(tup
然而,在 PHP 中,可以: only appears if $foo is true. only appears if $foo is false. 在 Javascript 中,能否在一个脚
XML有很多好处。它既是机器可读的,也是人类可读的,它具有标准化的格式,并且用途广泛。 它也有一些缺点。它是冗长的,不是传输大量数据的非常有效的方法。 XML最有用的方面之一是模式语言。使用模式,您可
由于长期使用 SQL2000,我并没有真正深入了解公用表表达式。 我给出的答案here (#4025380)和 here (#4018793)违背了潮流,因为他们没有使用 CTE。 我很欣赏它们对于递
我有一个应用程序: void deleteObj(id){ MyObj obj = getObjById(id); if (obj == null) { throw n
我的代码如下。可能我以类似的方式多次使用它,即简单地说,我正在以这种方式管理 session 和事务: List users= null; try{ sess
在开发J2EE Web应用程序时,我通常会按以下方式组织我的包结构 com.jameselsey.. 控制器-控制器/操作转到此处 服务-事务服务类,由控制器调用 域-应用程序使用的我的域类/对象 D
这更多是出于好奇而不是任何重要问题,但我只是想知道 memmove 中的以下片段文档: Copying takes place as if an intermediate buffer were us
路径压缩涉及将根指定为路径上每个节点的新父节点——这可能会降低根的等级,并可能降低路径上所有节点的等级。有办法解决这个问题吗?有必要处理这个吗?或者,也许可以将等级视为树高的上限而不是确切的高度? 谢
我有两个类,A 和 B。A 是 B 的父类,我有一个函数接收指向 A 类型类的指针,检查它是否也是 B 类型,如果是将调用另一个函数,该函数接受一个指向类型 B 的类的指针。当函数调用另一个函数时,我
有没有办法让 valgrind 使用多个处理器? 我正在使用 valgrind 的 callgrind 进行一些瓶颈分析,并注意到我的应用程序中的资源使用行为与在 valgrind/callgrind
假设我们要使用 ReaderT [(a,b)]超过 Maybe monad,然后我们想在列表中进行查找。 现在,一个简单且不常见的方法是: 第一种可能性 find a = ReaderT (looku
我的代码似乎有问题。我需要说的是: if ( $('html').attr('lang').val() == 'fr-FR' ) { // do this } else { // do
根据this文章(2018 年 4 月)AKS 在可用性集中运行时能够跨故障域智能放置 Pod,但尚不考虑更新域。很快就会使用更新域将 Pod 放入 AKS 中吗? 最佳答案 当您设置集群时,它已经自
course | section | type comart2 : bsit201 : lec comart2 :
我正在开发自己的 SDK,而这又依赖于某些第 3 方 SDK。例如 - OkHttp。 我应该将 OkHttp 添加到我的 build.gradle 中,还是让我的 SDK 用户包含它?在这种情况下,
随着 Rust 越来越充实,我对它的兴趣开始激起。我喜欢它支持代数数据类型,尤其是那些匹配的事实,但是对其他功能习语有什么想法吗? 例如标准库中是否有标准过滤器/映射/归约函数的集合,更重要的是,您能
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 9 年前。 Improve
我一直在研究 PHP 中的对象。我见过的所有示例甚至在它们自己的对象上都使用了对象构造函数。 PHP 会强制您这样做吗?如果是,为什么? 例如: firstname = $firstname;
...比关联数组? 关联数组会占用更多内存吗? $arr = array(1, 1, 1); $arr[10] = 1; $arr[] = 1; // <- index is 11; does the
我是一名优秀的程序员,十分优秀!