Chinaunix

标题: 求教 怎么获得调用函数的地址呢 [打印本页]

作者: ZhouGuaning    时间: 2011-07-06 10:52
标题: 求教 怎么获得调用函数的地址呢
大家好 偶新来的 第一次发帖就问问题 真不好意思呵

因为有点急。


也就是


void b()
{
    //怎么在这里获得调用者的地址呢
  
}
void a()
{
   b();
}

请各位大侠不吝赐教

看了一篇文章 用汇编的 在ebp里面 怎么怎么(额 不是很懂汇编)
文章

纯C++语句可以实现吗?
作者: cjaizss    时间: 2011-07-06 11:04
我真的很不欣赏这种调试手段
作者: yulihua49    时间: 2011-07-06 11:29
本帖最后由 yulihua49 于 2011-07-06 11:32 编辑
大家好 偶新来的 第一次发帖就问问题 真不好意思呵

因为有点急。


也就是


void b()
{
    / ...
ZhouGuaning 发表于 2011-07-06 10:52



    如果你的业务逻辑需要,可以参数传进来。
void b(void (*par)())
{
    //par就是调用者的地址
  
}
void a()
{
   b(a);
}
作者: ZhouGuaning    时间: 2011-07-06 11:37
无法传递函数指针进去啊 如果可以的话那就简单多了

void b(int ,int , int ,int )
{
    //因为我在做HOOK Func 所以调用者不是我的函数 我想在被调用者 里找出 调用者的地址...  
}
void a()
{
   b(1,1,1,1,);
}
作者: ZhouGuaning    时间: 2011-07-06 11:40
我真的很不欣赏这种调试手段
cjaizss 发表于 2011-07-06 11:04



    呵呵 这已经是最后一个办法了
作者: greensnow    时间: 2011-07-06 12:48
本帖最后由 greensnow 于 2011-07-06 13:06 编辑

返回地址在ebp+ 4里面, 你找到返回地址,
然后向上搜索"push %ebp, mov %esp, %ebp"的机器码;
运气好的话, 也许那是调用函数的起始地址..
作者: greensnow    时间: 2011-07-06 13:28
写了个演示性的代码, 在x86的gcc 4.45上测试通过

  1. #include <stdio.h>
  2. void *memrmem(const void *v, size_t size, const void *pat, size_t patsize) {
  3.     const char *p;
  4.     if (size < patsize)
  5.         return NULL;
  6.     if (patsize == 0)
  7.         return (void *) v;
  8.     for (p = v, p += size-patsize; size >= patsize; --p, --size)
  9.         if (memcmp(p, pat, patsize) == 0)
  10.             return (void *) p;
  11.     return NULL;
  12. }

  13. int search_caller() {
  14.     unsigned char * ptr, *caller;
  15.     asm volatile ("movl 4(%%ebp), %%eax; \
  16.                   movl %%eax, %0;"
  17.                   :"=g"(ptr)
  18.                   :
  19.                   :"%eax"
  20.                  );
  21.     caller = memrmem(ptr - 1000, 1000, "\x55\x89\xe5", 3);
  22.     if(caller) {
  23.         printf("0x%08X\n", caller);
  24.     }
  25. }

  26. int main(int argc, char *argv[]) {
  27.     search_caller();
  28.     printf("0x%08X\n", main);
  29.     return 0;
  30. }
复制代码

作者: OwnWaterloo    时间: 2011-07-06 13:31
回复 1# ZhouGuaning

纯C++ 应该是无解的。

特定于某个平台应该可行。 比如i386。

1. 获取返回地址
cl 有 _ReturnAddress 函数
gcc 有 __builtin_return_address 函数

如果编译器未知, 第1个参数的地址与返回地址的地址是相邻的。
void f(void* a0) { void* return_address = *(&a0-1); }

2. 从返回地址得到调用函数
逆向反汇编我感觉不靠谱。
还是从各种包含符号地址的文件中分析。
找入口地址比返回地址低的函数当中, 入口地址最高的那个。

3. hook
如果仅仅是为了hook, 有获取调用函数地址的必要么?
如果真能获取, 与hook有什么关系?

cl 可以使用 /hotpatch , 编译时在函数入口点插入2字节的无用代码。
链接时可使用 /functionminipading 在函数入口前加入填充。
这样就可以将2字节改为2字节的跳转指令, 跳转到填充处,  填充处再改写为5字节的跳转, 实现hook。

gcc 也有对应的选项, 忘记了……

直接在被调用处改变程序流向, 比在调用处一个一个改容易得多……
作者: ZhouGuaning    时间: 2011-07-06 13:57
本帖最后由 ZhouGuaning 于 2011-07-06 14:13 编辑
写了个演示性的代码, 在x86的gcc 4.45上测试通过
greensnow 发表于 2011-07-06 13:28



    gcc 真没用过这编译器
   大侠能写个vc6.0 或者vs的吗
  1.     asm volatile ("movl 4(%%ebp), %%eax; \
  2.                 movl %%eax, %0;"
  3.                 :"=g"(ptr)
  4.                 :
  5.                 :"%eax"
  6.                 );
复制代码
这里我看不明....
作者: ZhouGuaning    时间: 2011-07-06 14:03
回复  ZhouGuaning

纯C++ 应该是无解的。

特定于某个平台应该可行。 比如i386。

1. 获取返回地址 ...
OwnWaterloo 发表于 2011-07-06 13:31



    首先呢 我想截获目标程序调用sendto函数发送的目标数据写入txt文本  HOOK了sendto 函数
   由于目标程序调用sendto函数比较频繁 所以 我想筛选下
   把调用sendto函数的地址记录下来 然后把调用该函数发送无用数据的排除以外不写进txt
    剩下的就是我想要的数据啦




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2