我在目标进程中注入了自己的DLL,然后要在目标进程中写入一个5个字节的CALL XXX代码,XXX为我的DLL中的代码,请问在我的DLL代码中要如何保存和恢复哪些数据?假设目标进程中某处原来的代码是这样的
:0058CC24 53                      push ebx 
:0058CC25 32DB                    xor bl, bl 
:0058CC27 E835000000              call 0058CC61 
:0058CC2C 83F852                  cmp eax, 00000052 
:0058CC2F 741D                    je 0058CC4E 
:0058CC31 83F856                  cmp eax, 00000056 
:0058CC34 7418                    je 0058CC4E 
:0058CC36 3D76030000              cmp eax, 00000376  <-替换这里
:0058CC3B 7411                    je 0058CC4E 替换后
:0058CC24 53                      push ebx 
:0058CC25 32DB                    xor bl, bl 
:0058CC27 E835000000              call 0058CC61 
:0058CC2C 83F852                  cmp eax, 00000052 
:0058CC2F 741D                    je 0058CC4E 
:0058CC31 83F856                  cmp eax, 00000056 
:0058CC34 7418                    je 0058CC4E 
:0058CC36 3D76030000              call xxx  <-替换这里
:0058CC3B 7411                    je 0058CC4EDLL中 
XXX: cmp eax, 00000376  原来的代码复制到这里继续执行
      ...                这里要怎么做才能使程序不至于崩溃?   
      ret

解决方案 »

  1.   

    把所有的数据先压栈,ret之前在出栈行不行?
      

  2.   

    汇编版的版主vBin是个中高手,他的网站上有类似的改API函数的例子
      

  3.   

    一般来说就是保存一些寄存器的值吧?
    把有关的寄存器push,再pop
      

  4.   

    API Hook ? 为什么不看一下MS的Detour?
      

  5.   

    如果要自己写可以先保存要修改的地址再还原就可以了!!!
    如果在98内可以修改页属性或进入RING0修改!!!
    2000内可以由于加强了内存管理用内存读写API方便点!!!要获得RING0困难点你可以去www.driverdevelop.com看看例子!!!
      

  6.   

    我建议这样做将0058CC36替换为jmp xxx,并保存原来的数值xxx:pushad
        ...//做你要干的事    //完成后,将原来的指令恢复
        ...
        popad
        jmp 0058CC36最好不要在不同的地方执行原来的指令,因为x86指令长度不固定,你可能取出的不是一个完整的指令,所以将指令恢复后在jmp回去。需要保存所有使用的寄存器值,如果你的代码使用了FPU/MMX的话,还要保存fpu的寄存器,具体可以查MMX指令表里面有。
        
           
      

  7.   

    我试了一下用JMP,但有一个问题是JMP的时候会自动压栈返回地址,处理完后再跳回去的时候栈中的数据和原来不一样了,怎么办?
      

  8.   

    但有一个问题是JMP的时候会自动压栈返回地址,处理完后再跳回去的时候栈中的数据和原来不一样了,怎么办?如果只是多压了一个返回地址,随便用一个不用的寄存器pop一下不就可以了吗?
      

  9.   

    都说ret返回时会把栈中的返回地址赋值给ip寄存器,前题是你
    不能破坏栈中的数据,否则就不能正确返回
      

  10.   

    你的程序在哪里崩溃的,我觉得你的程序崩溃的原因是CALL指令没有5个字节,应用nop指令填充一下!!!
      

  11.   

    call才会自动压栈返回地址,jmp不会啊。
    跳回去的时候栈不一致也容易处理啊,add esp,4就可以了吧。
      

  12.   

    我也在作,不过我是在vxd里头修改。所以,没有系统的一些内存访问检查的问题。要注意的几个地方:
    jmp 后面的数值是offset ,目标地址是jmp下一条指令的地址+offset就是了。要注意:是下一条指令的地址。jmp 有near jmp and far jmp , far jmp 的机器码是0xe9,near jmp 好像是0xeb。最烦人的是计算offset.至于堆栈的处理,还是比较容易的。
      

  13.   

    回家去看windows高级编程吧。还超难问题呢。
      

  14.   

    首先要搞清楚你是要求改磁盘上的DLL文件的内容还是要修改载入内存中的DLL映象.如果是前者, 那应该是比较简单的,如果是后者, 我觉得堆栈平衡的问题很好解决, 主要难点在于如果找到DLL映象在内存中地线性地址, 以及获得相应的修改权限( 作出修改的代码需要具有RING0的权限, 或者事先修改了DLL映象所在段的选择子, 将该段的属性改为Rign3级的代码可以写的,这样就可以修改段内的数据而不会引起"...非法操作"了
      

  15.   

    我的已经可以了。只是做一些代码对齐的事情也要注意一下。我是在win98下vxd里头修改系统的一个服务的入口,c + asm 。赫赫。。
      

  16.   

    关于重用问题,欢迎加入讨论
    http://www.csdn.net/expert/topic/951/951819.xml?temp=.8591577
      

  17.   

    这段代码无法替换,cmp和Call的指令长度不一致的,不好替换
      

  18.   

    参考文献:
    AndrewSchulmanDavidMaxeyMattPietrek,《未公开的Windows核心技术》,清华大学出版社,1993年。王志东,“Windows中文环境”,《Windows软件的应用与开发》,1993.5。
      

  19.   

    Kevin_qing() 建议的方法是对的,将0058CC36替换为jmp xxx,并保存原来的数值xxx:pushad
        ...//做你要干的事    //完成后,将原来的指令恢复
        ...
        popad
        jmp 0058CC36另外 jmp 不会将返回地址压栈(call才会将返回地址压栈). 如果说堆栈乱了,可能
    是在你的DLL代码中出现了问题! 
    你的DLL中的代码形式(返汇编后的汇编指令)必须与Kevin_qing给出的代码相同,
    绝对不能通过 ret 之类的语句返回! 只能再次通过jmp返回