我有一些汇编代码,我想找出调用函数的原型(prototype),以便我可以从 C++ 代码中调用所有函数。
我真正想做的是将一个 dll 注入(inject)到正在运行的进程中,并从我的 dll 中调用正在运行的进程的函数。现在我已经成功注入(inject)了我的 dll 但不知道如何进行“调用”。
我是新手,对汇编代码了解不多。我的 dll 是用 visual c++ 2012 编写的。
这是运行过程的代码:
CPU Disasm
Address Hex dump Command Comments
6013BE24 /$ 53 PUSH EBX
6013BE25 |. 8B1D 10461860 MOV EBX,DWORD PTR DS:[60184610]
6013BE2B |. 8B1B MOV EBX,DWORD PTR DS:[EBX]
6013BE2D |. 8B40 04 MOV EAX,DWORD PTR DS:[EAX+4]
6013BE30 |. FFD3 CALL EBX
6013BE32 |. 5B POP EBX
6013BE33 \. C3 RETN
你可以看到 6013BE30 正在调用函数,而函数(EBX)在 004BAFAC
CPU Disasm
Address Hex dump Command Comments
004BAFAC /$ 55 PUSH EBP ; Test.004BAFAC(guessed void)
004BAFAD |. 8BEC MOV EBP,ESP
004BAFAF |. 53 PUSH EBX
004BAFB0 |. 8BD8 MOV EBX,EAX
004BAFB2 |. 8B43 08 MOV EAX,DWORD PTR DS:[EBX+8]
004BAFB5 |. E8 3EF40B00 CALL 0057A3F8 ; [Test.0057A3F8
004BAFBA |. 8B43 0C MOV EAX,DWORD PTR DS:[EBX+0C]
004BAFBD |. E8 36F40B00 CALL 0057A3F8 ; [Test.0057A3F8
004BAFC2 |. 8B43 14 MOV EAX,DWORD PTR DS:[EBX+14]
004BAFC5 |. E8 2EF40B00 CALL 0057A3F8 ; [Test.0057A3F8
004BAFCA |. 8B43 18 MOV EAX,DWORD PTR DS:[EBX+18]
004BAFCD |. E8 26F40B00 CALL 0057A3F8 ; [Test.0057A3F8
004BAFD2 |. 8B43 1C MOV EAX,DWORD PTR DS:[EBX+1C]
004BAFD5 |. E8 1EF40B00 CALL 0057A3F8 ; [Test.0057A3F8
004BAFDA |. 8B43 10 MOV EAX,DWORD PTR DS:[EBX+10]
004BAFDD |. E8 16F40B00 CALL 0057A3F8 ; [Test.0057A3F8
004BAFE2 |. 8B43 20 MOV EAX,DWORD PTR DS:[EBX+20]
004BAFE5 |. E8 0EF40B00 CALL 0057A3F8 ; [Test.0057A3F8
004BAFEA |. 8B43 44 MOV EAX,DWORD PTR DS:[EBX+44]
004BAFED |. E8 06F40B00 CALL 0057A3F8 ; [Test.0057A3F8
004BAFF2 |. 8B43 44 MOV EAX,DWORD PTR DS:[EBX+44]
那么如何在 Visual C++ 中调用 004BAFAC 处的函数呢?
最佳答案
在汇编函数中,参数从栈中弹出,从最后一个开始。因此,要将参数传递给函数,首先将它们压入堆栈,然后调用函数。在 MASM 中,这看起来类似于显示消息框:
.data
MsgBoxCaption db "Attention",0
MsgBoxText db "Hello Message Box!",0
.code
start:
push 0
mov eax, offset MsgBoxCaption
push eax
push offset MsgBoxText
push 0
call MessageBoxA
call ExitProcess
end start
虽然在 C++ 中它看起来像这样:
int retval = MessageBox(NULL, "Hello Message Box!", "Attention", 0);
用 OllyDbg 反汇编你会得到:
CPU Disasm
Address Hex dump Command Comments
011D13C0 |. 6A 00 PUSH 0 ; /Type = MB_OK|MB_DEFBUTTON1|MB_APPLMODAL
011D13C2 |. 68 54571D01 PUSH OFFSET 011D5754 ; |Caption = "Attention"
011D13C7 |. 68 3C571D01 PUSH OFFSET 011D573C ; |Text = "Hello Message Box!"
011D13CC |. 6A 00 PUSH 0 ; |hOwner = NULL
011D13CE |. FF15 40831D01 CALL DWORD PTR DS:[<&USER32.MessageBoxA> ; \USER32.MessageBoxA
返回值存储在 eax 中。您会看到,如果数据类型大于 DWORD(4 字节),您实际上不是在传递值,而是在传递引用。每个参数实际上只是一个 DWORD。这是因为堆栈在 32 位系统中是 32 位对齐的,因此只能保存 32 位值。寄存器的情况也是如此。在 32 位系统中,寄存器是 32 位宽。如果传递字符串,则传递的是对该字符串的引用,而不是字符串,也不是可变宽度的字符/字节数组。在 Integer 的情况下,它很可能作为值而不是引用传递。当在 MASM 中对函数进行原型(prototype)设计时,将所有参数作为 DWORD 进行原型(prototype)设计(但在 C++ 中则不行)。
因此在您上面的示例中,似乎有一个参数被传递到堆栈上(push ebx)。我说看起来像,因为它很可能只是将 ebx 推送到存储它以供以后检索(即,在再次弹出调用 ebx 之后 - 也许存储在 ebx 中的值需要保留)。您只能在实际运行实时调试 session 并观察堆栈/寄存器时才能确定。跳过调用并检查前后的堆栈指针 (esp) 以查看有多少参数传递给函数(同样:1 个参数 = 1 个 DWORD = 4 个字节)。
要在 C++ 中对您的函数进行原型(prototype)设计,您需要弄清楚参数的数据类型,可能是通过单步执行汇编代码并在围绕相关函数遍历代码时检查寄存器和/或堆栈。 eax 中的返回值也是如此。所以 eax 永远不会保存字符串,而可能是对字符串的引用,但它可能保存 32 位或更小的整数。您还必须通过逆向周围的代码来找出 eax 指向的数据类型。
编辑:实际上我写的东西有一半是错误的,最值得注意的是参数总是引用,所以请重读我写的东西。对于给您带来的不便,我们深表歉意 - 累了就不应该回答问题:)
关于c++ - 如何从汇编代码中找出函数原型(prototype)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15323056/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/