ASM.Net-x86仿真(译文)
By robot-v1.0
本文链接 https://www.kyfws.com/emulation/asm-net-x-emulation-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 6 分钟阅读 - 2553 个词 阅读量 0ASM.Net-x86仿真(译文)
原文地址:https://www.codeproject.com/Articles/305152/ASM-Net-x-Emulation
原文作者:Drag0nHunter
译文由本站 robot-v1.0 翻译
前言
ASM.Net a assembly x86 emulator which emulates the language the managed way
ASM.Net一个程序集x86仿真器,它以托管方式仿真语言
- 下载源代码-1.32 MB(Download source code - 1.32 MB) Asm.Net是一个用C#开发的程序集仿真器,它还将帮助您使用.NET Framework中的汇编器语言来开发程序.您还可以使用Asm.Net运行程序来模拟程序.(Asm.Net is an assembly emulator which is developed in C# which will also help you develop your programs using assembler language in the .NET Framework. You will also be able to run programs using Asm.Net for emulating programs.)
介绍(Introduction)
ASM.Net是一个汇编x86仿真器,它可以模拟汇编指令.尽管还不是全部.但是,有许多指令/操作码已经在起作用.可能足以让您在其中工作.(ASM.Net is an assembly x86 emulator which can emulate the instructions of assembly. Not all of them yet though. Yet there are a lot of instructions/opcodes which are already working. And may be enough for you to work in it.)
ASM.Net还能够将您编写的所有代码转换为字节数组,ASM.Net可以再次读取该字节数组以获取所有指令/变量/API.因此,您在ASM.Net中编写的代码都是可移植的,可以在另一台计算机上运行或处理,也可以在任何需要的地方进行而不会出现任何问题.但这还不是全部,ASM.Net能够生成的字节数组在每个部分都进行了加密,并经过压缩以使其远离窃贼,以防您的代码被盗.(ASM.Net is also able to convert all the code you write to a byte array which ASM.Net can read again to get all instructions/variables/APIs. So the code you write in ASM.Net is all portable and can be ran in another computer or processed or whereever you want without any problems. But this is not all, the byte array ASM.Net is able to generate is encrypted at every section and compressed to keep it away from thieves for your code.)
使用代码(Using the code)
在ASM.Net中使用代码很容易,但是您确实需要了解汇编的一些知识才能理解其中的任何内容,例如JMP,JNZ,CALL,XOR等…使用OpcodeWriter,我们可以编写代码,创建变量,还有更多.最后,当我们编写程序需要做的所有事情时,我们还可以使用ASM.Net调试器对其进行调试,看看一切是否都按预期工作.(Using the code in ASM.Net is easy but you really need to have some knowledge about assembly to understand any of it, e.g., JMP, JNZ, CALL, XOR and so on… With the OpcodeWriter we can write our code, create variables, and do more. At the end when we write everything that the program needs to do we can also debug it using the ASM.Net debugger and see if everything is working like expected.)
这是有关如何编写我们的MessageBox的示例代码:(This is an example code for how to write our MessageBox:)
OpcodeWriter writer = new OpcodeWriter();
//Call MessageBox
writer.codeSection.PUSH_VALUE(0); //push a value to stack
//ASM.Net creates a new variable and pushes the address of it to stack
writer.codeSection.PUSH_STRING("Title here");
writer.codeSection.PUSH_STRING("Hello CodeProject!");
writer.codeSection.PUSH_VALUE(0); //push a value to stack
writer.codeSection.CALL(Functions.User32_MessageBoxA); //call our MessageBox
AsmNet asmNet = new AsmNet(writer.Generate(true)); //initialize ASM.Net
Processor Cpu = asmNet.InitializeCPU(); //initialize the CPU to be able to execute our code
Cpu.RunLoop(); //execute the code we wrote
如您所见,显示MessageBox不需要太多代码.可能已经注意到,ASM.Net仅需要一个参数,即我告诉过的字节数组.的(As you can see it’s not that much code to show a MessageBox. And as may have noticed ASM.Net only needs one argument which is the byte array I told you about. The) OpcodeWriter
能够使用(is able to convert to a byte array using the) Generate
功能.的(function. The) True
您将其视为(you see as argument for the) Generate
功能是检查每个(function is to check every) JUMP
运行时错误的地址.这样可以防止在与他人共享之前在运行时出错.(address for errors at runtime. This could prevent errors at runtime before you would share it with others.)
但是,显示一个简单的MessageBox并不是ASM.Net所能做的,它还能做的更多.这是一个简单的TCP服务器:(But showing a simple MessageBox is not all ASM.Net can do, it can do a lot more. This is a simple TCP server:)
OpcodeWriter writer = new OpcodeWriter();
WSAData wsaData = new WSAData();
sockaddr_in sockaddr = new sockaddr_in();
sockaddr_in Clientsockaddr = new sockaddr_in();
VirtualAddress wsaDataAddr = writer.dataSection.CreateVariable(wsaData);
VirtualAddress SockinAddress = writer.dataSection.CreateVariable(sockaddr);
VirtualAddress ClientSockinAddress = writer.dataSection.CreateVariable(Clientsockaddr);
VirtualAddress ArrayAddress =
writer.dataSection.CreateVariable(ASCIIEncoding.ASCII.GetBytes(":)"));
//the data we want to send when a client connects
//socket initialization
//set the WSADATA settings
writer.codeSection.MOV_VARIABLE_VALUE(wsaDataAddr, "HighVersion", (ushort)2);
writer.codeSection.MOV_VARIABLE_VALUE(wsaDataAddr, "Version", (ushort)2);
//set the sockaddr_in settings, setting the family IPv4
writer.codeSection.MOV_VARIABLE_VALUE(SockinAddress,
"sin_family", (short)ValueCodes.InterNetworkv4);
//setting port, we need to encode it first...
writer.codeSection.PUSH_VALUE(1337); //1337=listen port
writer.codeSection.CALL(Functions.ws2_32_htons);
writer.codeSection.MOV_VARIABLE_REGISTER(SockinAddress, "sin_port", Register.EAX);
writer.codeSection.PUSH_VARIABLE(wsaDataAddr);
writer.codeSection.PUSH_VALUE(36);
writer.codeSection.CALL(Functions.ws2_32_WSAStartup);
//started successfully ?
writer.codeSection.MOV_ECX(0);
writer.codeSection.CMP(CmpRegisterOpcodes.CMP_ECX_EAX);
writer.codeSection.JNE("failed");
//create a socket
writer.codeSection.PUSH_VALUE(ValueCodes.Tcp, (int)0);
writer.codeSection.PUSH_VALUE(ValueCodes.Stream, (int)0);
writer.codeSection.PUSH_VALUE(ValueCodes.InterNetworkv4, (int)0);
writer.codeSection.CALL(Functions.ws2_32_socket);
//is socket > 0 ?
writer.codeSection.MOV_ECX((int)ValueCodes.INVALID_SOCKET);
writer.codeSection.CMP(CmpRegisterOpcodes.CMP_ECX_EAX);
writer.codeSection.JE("failed");
//lets move our socket handle to EBX
writer.codeSection.MOV(MovRegisterOpcodes.MOV_EBX_EAX);
//lets bind our socket
writer.codeSection.PUSH_VALUE(Marshal.SizeOf(sockaddr));
writer.codeSection.PUSH_VARIABLE(SockinAddress); //our sockaddr_in
writer.codeSection.PUSH_EBX(); //socket handle
writer.codeSection.CALL(Functions.ws2_32_bind);
//ok lets listen at a port
writer.codeSection.PUSH_VALUE((int)100);
writer.codeSection.PUSH_EBX(); //socket
writer.codeSection.CALL(Functions.ws2_32_listen);
//now a infinite loop for accept our connections but lets setup our console
writer.codeSection.PUSH_VALUE(-11); //STD_OUTPUT_HANDLE
writer.codeSection.CALL(Functions.Kernel32_GetStdHandle);
writer.codeSection.MOV(MovRegisterOpcodes.MOV_EDX_EAX);
writer.codeSection.CreateLabel("loop");
//lets accept connections
writer.codeSection.PUSH_VALUE(Marshal.SizeOf(Clientsockaddr));
writer.codeSection.PUSH_VARIABLE(ClientSockinAddress);
writer.codeSection.PUSH_EBX(); //server socket
writer.codeSection.CALL(Functions.ws2_32_accept);
writer.codeSection.MOV(MovRegisterOpcodes.MOV_EDI_EAX); //set client socket to EDI
writer.codeSection.PUSH_VALUE(0);
writer.codeSection.PUSH_VALUE(0);
writer.codeSection.PUSH_VALUE(20);//char length
writer.codeSection.PUSH_STRING("new client accepted\r\n");
writer.codeSection.PUSH_EDX();
writer.codeSection.CALL(Functions.Kernel32_WriteConsoleA);
//lets send a packet
writer.codeSection.PUSH_VALUE(0);
writer.codeSection.PUSH_VALUE(2);
writer.codeSection.PUSH_VARIABLE(ArrayAddress);
writer.codeSection.PUSH_EDI(); //client socket
writer.codeSection.CALL(Functions.ws2_32_send);
//close our connection with the client...
writer.codeSection.PUSH_EDI();
writer.codeSection.CALL(Functions.ws2_32_closesocket);
writer.codeSection.JMP("loop");
writer.codeSection.PUSH_EBX();
writer.codeSection.CALL(Functions.ws2_32_closesocket);
writer.codeSection.CreateLabel("failed");
writer.codeSection.XOR(XorRegisterOpcodes.XOR_ECX_ECX);
阅读代码时,您会发现一些JUMP,Calls等.但是此示例用于启动一个简单的TCP服务器,该服务器接受连接并发送一个简单的笑脸.(When you are reading through the code, you will find some JUMPs, Calls etc. But this example is for starting a simple TCP server which accepts connections and sends a simple smiley face “) " align =” top" src =" http://www.codeproject.com/script/Forums/Images/smiley_smile.gif"/>"连接到一个连接的人.正如您在此图像中看到的那样,它正在等待新的连接.顺便说一句,不要以为它是Linux,而只是带有Ubuntu主题的Windows 7:(" align=“top” src=“http://www.codeproject.com/script/Forums/Images/smiley_smile.gif" /> " to the one who connects. As you can see here in this image it’s waiting for a new connection. By the way don’t think it’s Linux it’s just Windows 7 with an Ubuntu theme:)
好的,让我们在Windows” telnet 127.0.0.1 1337"的命令行中进行操作:(OK, so let’s do for example in our command line of Windows “telnet 127.0.0.1 1337”:)
如您所见,当我在命令行中按Enter时,它带有一个笑脸:(As you can see when I pressed Enter in the command line it came up with a smiley face:)
如您所见,(As you could see the “) 出现并且工作得很好,并且在另一个控制台上写了一些新连接被接受(在上面查找TCP服务器中的代码).为了使调试更容易一些,让我们看看JUMP的去向:(” align=“top” src=“http://www.codeproject.com/script/Forums/Images/smiley_smile.gif" /> " came up and it worked just fine and something to another console was written that a new connection was accepted (look above for the code in the TCP server). And to make debugging a little more easier let’s see where our JUMPs are going:)
如您所见,红线立即向我们显示了JUMP的去向.如果有任何问题,我想回答.但是您还应该稍微深入一点代码.也有可以使用的事件等.(As you can see the red line shows us instantly where the JUMP is going to. If there are any questions I’d love to answer those. But you also should need to dig in the code a little. There are also events etc., that you can use.)
兴趣点(Points of Interest)
在制作ASM.Net时,我需要笑一点,因为我现在可以编写可移植的代码,而不必使用CodeDom了,因为它会产生错误,因为(While making ASM.Net I needed to laugh a little because I can now write portable code instead of using CodeDom which can give errors because a)**.dll(.dll)**会丢失任何内容,并将其代码转储到临时目录中,人们可以从中访问和窃取代码.(is missing whatsoever and dumps its code to a temp directory that people can access and steal the code from.)
ASM.Net可以在任何地方运行,但仍然需要ASM.Net库,甚至不需要将其转储到硬盘驱动器中.(And ASM.Net can run anywhere but it still needs the ASM.Net library and don’t even need to be dumped to the hard drive if not needed.)
历史(History)
您可以签出我们的SVN:(You can checkout our SVN:)
- CodePlex:(CodePlex:) http://asmdotnet.codeplex.com/(http://asmdotnet.codeplex.com/)
- SVN:(SVN:) https://asmdotnet.svn.codeplex.com/svn(https://asmdotnet.svn.codeplex.com/svn)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
VB9.0 C# VB ASM C#3.0 WinXP Win2003 Vista .NET3.0 .NET2.0 新闻 翻译