{"id":2802,"date":"2010-01-26T23:03:00","date_gmt":"2010-01-26T22:03:00","guid":{"rendered":"http:\/\/www.corelan.be:8800\/?p=2802"},"modified":"2026-03-22T10:15:58","modified_gmt":"2026-03-22T09:15:58","slug":"starting-to-write-immunity-debugger-pycommands-my-cheatsheet","status":"publish","type":"post","link":"https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/","title":{"rendered":"Starting to write Immunity Debugger PyCommands : my cheatsheet"},"content":{"rendered":"<p>When I started Win32 exploit development many years ago, my preferred debugger at the time was WinDbg (and some Olly). While Windbg is a great and fast debugger, I quickly figured out that some additional\/external tools were required to improve my exploit development experience.<\/p>\n<p>Despite the fact that the command line oriented approach in windbg has many advantages, it appeared not the best tool to search for good jump addresses, or to list non-safeseh compiled \/ non-aslr aware modules, etc\u2026.&#160; Ok, looking for a simple \u201cjmp esp\u201d is trivial, but what if you are looking for all pop pop ret combinations in non-safeseh compiled modules\u2026&#160;&#160; Not an easy task.<\/p>\n<p>It is perfectly possible to build plugins for Windbg, but the ones that I have found (MSEC, byakugan (Metasploit)) don\u2019t always work the way I want them to work, and would still not solve some issues I was having while writing exploits.<\/p>\n<p><a href=\"http:\/\/www.ollydbg.de\/\" target=\"_blank\" rel=\"noopener\">OllyDbg<\/a> and <a href=\"http:\/\/debugger.immunityinc.com\/\" target=\"_blank\" rel=\"noopener\">Immunity Debugger<\/a> are quite different than windbg.&#160; Not only the GUI is very much different, the number of plugins for these debuggers is substantially higher.&#160; After evaluating both of them (they pretty much have the same look and feel), and evaluating the way plugins can be added, I made the decision to focus on Immunity Debugger.<\/p>\n<p>That does not mean OllyDbg is a bad debugger or is limited in what you can do in terms of writing plugins\u2026 I just found it harder to \u201cquickly tweak a plugin\u201d while building an exploit.&#160;&#160; OllyDbg plugins are compiled into dll\u2019s, so changing a plugin would require me to recompile and test.&#160;&#160; Immunity Debugger uses python scripts.&#160; I can go into the script, make a little change, and see the results right away.&#160; Simple.<\/p>\n<p>Both OllyDbg and Immunity Debugger have a good amount of plugins (either contributed by the community or made available when you installed the product).&#160;&#160; While there is nothing wrong with these plugins (or PyCommands in case of Immunity Dbg), I really wanted to have a single plugin that would help me building all (stack based) exploits, from A to Z.&#160; This idea got translated into my <a href=\"https:\/\/github.com\/corelan\/mona\" target=\"_blank\" rel=\"noopener\">pvefindaddr<\/a> PyCommand.<\/p>\n<p>My obvious choice was Immunity &amp; Python.&#160; I\u2019m not a great python developer (at all), but I have been able to build my own PyCommand in a relatively short amount of time. This proves that it\u2019s really easy to build custom PyCommands for Immunity, even if you are not an expert developer.&#160; If I can do it, then you can for sure.<\/p>\n<p>The only issue I faced (apart from learning python syntax and getting used to python\u2019s hmmmm \u201cslightly annoying\u201d indentation requirement) was finding out how the Immunity-specific API\u2019s\/methods\/attributes work.&#160;&#160; To be honest, the API help included with Immunity Debugger was not a great help. It basically only lists the available methods\/attributes\/\u2026 and that\u2019s it.&#160; No explanation on what these methods &amp; attributes behave, on what they\u2019re supposed to do, or how to use them for that matter.&#160;&#160; Ok, once you start understanding how things work, they are still a good reference, but when you are learning from scratch, a little persistence may be required.<\/p>\n<p>Luckily, since Immunity comes with a lot of PyCommands, those can be used as a reference.<\/p>\n<p>Anyways, it\u2019s still a good idea to use the ImmDbg Python API help file too. You can get access to the API help in Immunity by navigating to \u201cHelp\u201d, select \u201cSelect API help file\u201d, and selecting the IMMLIB.HLP file from the Documentation folder.<\/p>\n<p><a href=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image52.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px\" height=\"164\" alt=\"image\" src=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb52.png\" width=\"387\" border=\"0\" \/><\/a><\/p>\n<p>From that point forward, you can access this help file via \u201cHelp\u201d - \u201cOpen API help file\u201d<\/p>\n<p><a href=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image53.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px\" height=\"169\" alt=\"image\" src=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb53.png\" width=\"380\" border=\"0\" \/><\/a><\/p>\n<p>Immunity also has an online version of the API : http:\/\/debugger.immunityinc.com\/update\/Documentation\/ref\/&#160; (online version contains a little bit more information)<\/p>\n<p>My main goal today is putting together a reference\/cheatsheet for anyone interested in writing pycommands, so you can start building your own plugins faster than I did \ud83d\ude42 ). This is not going to be \u201cthe complete reference\u201d, but it should help you start to build your own plugins.<\/p>\n<p>First of all, the python syntax that you will need to write (or learn and write) is based on python 2.x&#160;&#160; (If you are not familiar with python : v2.x and v3.x are quite different in certain areas, so if you want to get yourself a reference\/book on writing python, make sure to pick one that is based on the 2.x branch)<\/p>\n<p>&#160;<\/p>\n<p>&#160;<\/p>\n<h3>Building a PyCommand from scratch<\/h3>\n<p>Start by creating a file in the Immunity Debugger PyCommands folder : &lt;filename&gt;.py<\/p>\n<p>This filename is important, because you will need to launch the PyCommand based on the filename.<\/p>\n<h4>Launching a PyCommand<\/h4>\n<p>Launching a PyCommand is really easy : just type in the filename (without the .py extension, but prepended with an exclamation mark), in the command box at the bottom of Immunity Debugger<\/p>\n<p><a href=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image54.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px\" height=\"228\" alt=\"image\" src=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb54.png\" width=\"270\" border=\"0\" \/><\/a><\/p>\n<p>So if you named your plugin \u201cplugin1.py\u201d, then you can launch the script by executing<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #282828\">!plugin1<\/pre>\n<h4>Basic structure<\/h4>\n<p>The basic structure of a plugin looks like this :<\/p>\n<p>- load the Immunity Libraries (and perhaps other libraries, depending on what you want to do)<\/p>\n<p>- write a main() function that will read the command line arguments (if any) and call functions based on what you want the plugins to do<\/p>\n<p>- write the functions that will perform the required actions<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\">#!\/usr\/bin\/env python \"<span style=\"color: #7fec7f\"><\/span>\"\" (c) Peter Van Eeckhoutte 2009 U{Peter Van Eeckhoutte - corelan.<http:<span style=\"color: #d7df01\">\/\/www.corelan.be>}<\/span> peter.ve@corelan.be corelanc0d3r \"<span style=\"color: #7fec7f\"><\/span>\"\" __VERSION__ = '1.0' <span style=\"color: #5576D1\">import<\/span> immlib <span style=\"color: #5576D1\">import<\/span> getopt <span style=\"color: #5576D1\">import<\/span> immutils from immutils <span style=\"color: #5576D1\">import<\/span> * \"<span style=\"color: #7fec7f\"><\/span>\"\"\"<span style=\"color: #7fec7f\"><\/span>\"\"\"<span style=\"color: #7fec7f\"><\/span>\"\"\"<span style=\"color: #7fec7f\"><\/span>\"\" Functions \"<span style=\"color: #7fec7f\"><\/span>\"\"\"<span style=\"color: #7fec7f\"><\/span>\"\"\"<span style=\"color: #7fec7f\"><\/span>\"\"\"<span style=\"color: #7fec7f\"><\/span>\"\" \"<span style=\"color: #7fec7f\"><\/span>\"\"\"<span style=\"color: #7fec7f\"><\/span>\"\"\"<span style=\"color: #7fec7f\"><\/span>\"\"\"<span style=\"color: #7fec7f\"><\/span>\"\"\"<span style=\"color: #7fec7f\"><\/span>\"\"\"<span style=\"color: #7fec7f\"><\/span>\"\" Main application \"<span style=\"color: #7fec7f\"><\/span>\"\"\"<span style=\"color: #7fec7f\"><\/span>\"\"\"<span style=\"color: #7fec7f\"><\/span>\"\"\"<span style=\"color: #7fec7f\"><\/span>\"\"\"<span style=\"color: #7fec7f\"><\/span>\"\"\"<span style=\"color: #7fec7f\"><\/span>\"\" <span style=\"color: #5576D1\">def<\/span> main(args):<\/pre>\n<p>Next, you will need to specify you want to use the Immunity Debugger libraries and use them in your script.&#160; The best way to do is by declaring a variable that hooks into the Immunity debugger class:<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #282828\">imm = immlib.Debugger()<\/pre>\n<p>I usually make this one global, so I keep it outside of the main() function.&#160; (You can put it directly below the \u201cimport\u201d statements for example)<\/p>\n<p>The list of available classes are :<\/p>\n<p><a href=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image55.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px\" height=\"386\" alt=\"image\" src=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb55.png\" width=\"234\" border=\"0\" \/><\/a><\/p>\n<p>&#160;<\/p>\n<p>&#160;<\/p>\n<h4>Handling arguments<\/h4>\n<p>The arguments\/parameters specified when launching the PyCommand are captured in the \u201cargs\u201d array.<\/p>\n<p>You can get the number of arguments using <\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #282828\">len(args)<\/pre>\n<p>Accessing the arguments themselves is as easy as iterating through the args[] array and getting the contents of an element in the array:<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\"><span style=\"color: #5576D1\">def<\/span> main(args): <span style=\"color: #5576D1\">if<\/span> not args: usage() <span style=\"color: #5576D1\">else<\/span>: <span style=\"color: #5576D1\">print<\/span> \"<span style=\"color: #7fec7f\">Number of arguments : <\/span>\" + str(len(args)) cnt=0 while (cnt < len(args)): <span style=\"color: #5576D1\">print<\/span> \"<span style=\"color: #7fec7f\"> Argument <\/span>\" + str(cnt+1)+\"<span style=\"color: #7fec7f\"> : <\/span>\" + <strong><font color=\"#ff0000\">args[cnt]<\/font><\/strong> cnt=cnt+1<\/pre>\n<p>&#160;<\/p>\n<p>&#160;<\/p>\n<h3>Writing to log, tables, files<\/h3>\n<p>You may have noticed that the script above does not seem to output anything.&#160; While the syntax is perfectly correct, there is no visible default output window, so you will have to tell the plugin where to write the output to.<\/p>\n<p>There are a couple of options : you can write to the Immunity Log window (which is the most commonly used technique), a new\/separate table (which is nothing more than a new window that can list the information in a table), or to a file (which may be a good idea if the amount of output you are generating would overflow the Log window buffer.<\/p>\n<h4>Writing output to the Log Window<\/h4>\n<p>The Log Window is a part of the debugger. So we will need to use the debugger instance that we have declared earlier (imm) to write to the Log.<\/p>\n<p>The method to do so is simple :&#160;&#160; imm.Log()<\/p>\n<p><a href=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image56.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px\" height=\"245\" alt=\"image\" src=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb56.png\" width=\"219\" border=\"0\" \/><\/a><\/p>\n<p>There are a couple of things you can do, so let\u2019s have a look at this example :<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\"><span style=\"color: #5576D1\">def<\/span> main(args): <span style=\"color: #5576D1\">print<\/span> \"<span style=\"color: #7fec7f\">Number of arguments : <\/span>\" + str(len(args)) imm.Log(\"<span style=\"color: #7fec7f\">Number of arguments : %d <\/span>\" % len(args)) cnt=0 while (cnt < len(args)): imm.Log(\"<span style=\"color: #7fec7f\"> Argument %d : %s<\/span>\" % (cnt+1,args[cnt])) <span style=\"color: #5576D1\">if<\/span> (args[cnt] == \"<span style=\"color: #7fec7f\">world<\/span>\"): imm.Log(\"<span style=\"color: #7fec7f\"> You said %s !<\/span>\" % (args[cnt]),focus=1, highlight=1) cnt=cnt+1<\/pre>\n<p><a href=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image57.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px\" height=\"170\" alt=\"image\" src=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb57.png\" width=\"316\" border=\"0\" \/><\/a><\/p>\n<p>You can specify a custom memory address in the left column of the Log Window. (If nothing is specified, this address will be 0BADF00D.) All you need to do is specify the memory address (integer !) as second argument for the Log() method :<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\"><span style=\"color: #5576D1\">def<\/span> main(args): <span style=\"color: #5576D1\">print<\/span> \"<span style=\"color: #7fec7f\">Number of arguments : <\/span>\" + str(len(args)) imm.Log(\"<span style=\"color: #7fec7f\">Number of arguments : %d <\/span>\" % len(args)) cnt=0 while (cnt < len(args)): imm.Log(\"<span style=\"color: #7fec7f\"> Argument %d : %s<\/span>\" % (cnt+1,args[cnt])<strong><font color=\"#ff0000\">,12345678<\/font><\/strong>) <span style=\"color: #5576D1\">if<\/span> (args[cnt] == \"<span style=\"color: #7fec7f\">world<\/span>\"): imm.Log(\"<span style=\"color: #7fec7f\"> You said %s !<\/span>\" % (args[cnt]),focus=1, highlight=1) cnt=cnt+1<\/pre>\n<p><a href=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image58.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px\" height=\"136\" alt=\"image\" src=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb58.png\" width=\"329\" border=\"0\" \/><\/a><\/p>\n<p>&#160;<\/p>\n<p>A good way to start your plugin, handling \u201cno arguments\u201d by displaying a \u201cUsage\u201d text, could be something like this :<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\">__VERSION__ = '1.0' <span style=\"color: #5576D1\">import<\/span> immlib <span style=\"color: #5576D1\">import<\/span> getopt <span style=\"color: #5576D1\">import<\/span> immutils from immutils <span style=\"color: #5576D1\">import<\/span> * imm = immlib.Debugger() \"<span style=\"color: #7fec7f\"><\/span>\"\" Functions \"<span style=\"color: #7fec7f\"><\/span>\"\" <span style=\"color: #5576D1\">def<\/span> usage(): imm.Log(\"<span style=\"color: #7fec7f\"> ** No arguments specified ** <\/span>\") imm.Log(\"<span style=\"color: #7fec7f\"> Usage : <\/span>\") imm.Log(\"<span style=\"color: #7fec7f\"> blah blah<\/span>\") \"<span style=\"color: #7fec7f\"><\/span>\"\" Main application \"<span style=\"color: #7fec7f\"><\/span>\"\" <span style=\"color: #5576D1\">def<\/span> main(args): <span style=\"color: #5576D1\">if<\/span> not args: usage() <span style=\"color: #5576D1\">else<\/span>: imm.Log(\"<span style=\"color: #7fec7f\">Number of arguments : %d <\/span>\" % len(args)) cnt=0 while (cnt < len(args)): imm.Log(\"<span style=\"color: #7fec7f\"> Argument %d : %s<\/span>\" % (cnt+1,args[cnt])) <span style=\"color: #5576D1\">if<\/span> (args[cnt] == \"<span style=\"color: #7fec7f\">world<\/span>\"): imm.Log(\"<span style=\"color: #7fec7f\"> You said %s !<\/span>\" % (args[cnt]),focus=1, highlight=1) cnt=cnt+1<\/pre>\n<p>&#160;<\/p>\n<h4>Updating log\/table<\/h4>\n<p>You will notice, as you continue to build your plugin, that when you search through memory (or perform any other CPU intensive task), the log window may not get updated right away.&#160; Immunity may appear to be hanging for a while, and when everything completes, everything is shown in the log window (or table for that matter).<\/p>\n<p>There is a way to influence this behaviour.&#160; After each imm.Log() call, you can force Immunity Debugger to update the log window. This is as easy as writing the following statement in your code :<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #282828\">imm.updateLog()<\/pre>\n<p>The only (big) disadvantage is that it will also slow down the CPU intensive task that you were performing.&#160; So it\u2019s a trade off between seeing what happens in real time, and speed.&#160; It\u2019s up to you to decide.<\/p>\n<p>&#160;<\/p>\n<p>&#160;<\/p>\n<h4>Writing output to a table<\/h4>\n<p>Writing data to the Log allows you to display both structured and unstructured data. First, you must define the table (Table title + colum titles), and then you can use the .add() method on the table object to add data to the table :<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\"><span style=\"color: #5576D1\">def<\/span> main(args): <span style=\"color: #5576D1\">if<\/span> not args: usage() <span style=\"color: #5576D1\">else<\/span>: #create table table=imm.createTable('Argument table',['Number','Argument']) imm.Log(\"<span style=\"color: #7fec7f\">Number of arguments : %d <\/span>\" % len(args)) cnt=0 while (cnt < len(args)): table.<span style=\"color: #5576D1\">add<\/span>(0,[\"<span style=\"color: #7fec7f\">%d<\/span>\"%(cnt+1),\"<span style=\"color: #7fec7f\">%s<\/span>\"%(args[cnt])]) cnt=cnt+1<\/pre>\n<p><a href=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image59.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px\" height=\"255\" alt=\"image\" src=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb59.png\" width=\"381\" border=\"0\" \/><\/a><\/p>\n<p>&#160;<\/p>\n<h4>Writing output to a file<\/h4>\n<p>Writing output to the Log or a table works fine, as long as the amount of data doesn\u2019t overflow the available amount of Log buffer space.&#160; If that is the case, you could consider writing output to file as well as to Log or a table.<\/p>\n<p>This is not Immunity specific in any way - it\u2019s just python code.<\/p>\n<p>When writing files, by default, the files will be written into the Immunity Debugger program folder. The technique is simple :<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\">filename=\"<span style=\"color: #7fec7f\">myfile.txt<\/span>\" FILE=<span style=\"color: #5576D1\">open<\/span>(filename,\"<span style=\"color: #7fec7f\">a<\/span>\") #this will append to the file FILE.<span style=\"color: #5576D1\">write<\/span>(\"<span style=\"color: #7fec7f\">Blah blah<\/span>\" + \"<span style=\"color: #7fec7f\">\\n<\/span>\") FILE.<span style=\"color: #5576D1\">close<\/span>()<\/pre>\n<p>What I usually do is this : First, I clear the contents of the file, then I append data to the file using a function (tofile())<\/p>\n<p>Clearing the contents of a file can be done like this :<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\"><span style=\"color: #5576D1\">def<\/span> resetfile(file1): FILE=<span style=\"color: #5576D1\">open<\/span>(file1,\"<span style=\"color: #7fec7f\">w<\/span>\") FILE.<span style=\"color: #5576D1\">write<\/span>(\"<span style=\"color: #7fec7f\"><\/span>\") FILE.<span style=\"color: #5576D1\">close<\/span>() <span style=\"color: #5576D1\">return<\/span> \"<span style=\"color: #7fec7f\"><\/span>\" <\/pre>\n<p>At the beginning of a function, I reset the file, and in the function, I use the tofile() function to write data into the file<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\"><span style=\"color: #5576D1\">def<\/span> tofile(info,filename): info=info.<span style=\"color: #5576D1\">replace<\/span>('\\n',' - ') FILE=<span style=\"color: #5576D1\">open<\/span>(filename,\"<span style=\"color: #7fec7f\">a<\/span>\") FILE.<span style=\"color: #5576D1\">write<\/span>(info+\"<span style=\"color: #7fec7f\">\\n<\/span>\") FILE.<span style=\"color: #5576D1\">close<\/span>() <span style=\"color: #5576D1\">return<\/span> \"<span style=\"color: #7fec7f\"><\/span>\"<\/pre>\n<\/p>\n<h4>Working with addresses<\/h4>\n<p>When you have to display a memory address, or use a memory address in a function, then you must verify what the required format of the address should be : either a string (if you only want to display the address) or an integer (if the address is used in Immunity methods)<\/p>\n<p>When Immunity returns an address or expects you to provide an address, it will be an integer. If you want to display this address on screen, write to a log file, etc\u2026 you\u2019ll have to use a format string to convert it to readable format :<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\"><span style=\"color: #5576D1\">def<\/span> usage(): imm.Log(\"<span style=\"color: #7fec7f\"> ** No arguments specified ** <\/span>\") imm.Log(\"<span style=\"color: #7fec7f\"> Usage : <\/span>\") imm.Log(\"<span style=\"color: #7fec7f\"> blah blah<\/span>\") <span style=\"color: #5576D1\">def<\/span> tohex(intAddress): <span style=\"color: #5576D1\">return<\/span> \"<span style=\"color: #7fec7f\">%08X<\/span>\" % intAddress \"<span style=\"color: #7fec7f\"><\/span>\"\" Main application \"<span style=\"color: #7fec7f\"><\/span>\"\" <span style=\"color: #5576D1\">def<\/span> main(args): <span style=\"color: #5576D1\">if<\/span> not args: usage() <span style=\"color: #5576D1\">else<\/span>: myAddress=1234567 #integer address imm.Log(\"<span style=\"color: #7fec7f\"> Integer : %d <\/span>\" % myAddress,address=myAddress) imm.Log(\"<span style=\"color: #7fec7f\"> Readable hex : 0x%08X<\/span>\" % myAddress,address=myAddress) hexAddress = tohex(myAddress) imm.Log(\"<span style=\"color: #7fec7f\"> Readable string : 0x%s<\/span>\" % hexAddress,address=myAddress) imm.Log(\"<span style=\"color: #7fec7f\"> Back to integer : %d<\/span>\" % int(hexAddress,16),address=int(hexAddress,16))<\/pre>\n<p><a href=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image61.png\" target=\"_blank\" rel=\"noopener external noreferrer\" class=\"thickbox no_icon\" data-wpel-link=\"external\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px\" height=\"156\" alt=\"image\" src=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb61.png\" width=\"367\" border=\"0\" \/><\/a><\/p>\n<blockquote>\n<p>Remember : anytime the Immunity API says a method uses \u201caddress\u201d, you need to specify an integer value.<\/p>\n<\/blockquote>\n<p>Ok, that\u2019s all we need to know for now \u2013 we can start writing code that will actually do something usefull and display the output to log, table, file, \u2026<\/p>\n<\/p>\n<h3>Using opcodes, assemble and disassemble, and searching memory<\/h3>\n<p>One of the most common things you\u2019ll probably want to do is search through memory, looking for specific type of information. Some examples could be<\/p>\n<p>\u2013 finding jump addresses (jump, call, push+ret, pop pop ret, etc)<\/p>\n<p>\u2013 comparing bytes in memory with bytes in a file (so step through memory locations, read bytes, and do something with it)<\/p>\n<p>\u2013 etc<\/p>\n<p>In certain cases, you\u2019ll probably also want to convert opcodes to instructions, and vice versa.<\/p>\n<p>Let\u2019s take it step by step. Suppose you want to search for all jmp esp instructions available in memory. First of all, there has to be a process attached to Immunity before your search will produce results. No process = no results \ud83d\ude42<\/p>\n<p>There are 2 ways to perform a search. You can provide the asm code, use Immunity to convert it to opcodes, and perform the search; or you can provide the opcode and perform the search.<\/p>\n<p>Example 1 : search for \u201cjmp esp\u201d<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\"><span style=\"color: #5576D1\">def<\/span> main(args): imm.Log(\"<span style=\"color: #7fec7f\">Started search for jmp esp...<\/span>\") imm.updateLog() searchFor=\"<span style=\"color: #7fec7f\">jmp esp<\/span>\" results=imm.Search( imm.Assemble (searchFor) ) for result in results: imm.Log(\"<span style=\"color: #7fec7f\">Found %s at 0x%08x <\/span>\" % (searchFor, result), address = result) <\/pre>\n<p>That wasn\u2019t too bad, was it ?<\/p>\n<p>Example 2 : If you want to search for a serie of instructions (such as \u201cpush esp + ret\u201d), then the instructions must be separated by \\n :<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\"><span style=\"color: #5576D1\">def<\/span> main(args): imm.Log(\"<span style=\"color: #7fec7f\">Started search for push esp \/ ret...<\/span>\") imm.updateLog() searchFor=\"<span style=\"color: #7fec7f\">push esp\\nret<\/span>\" results=imm.Search( imm.Assemble (searchFor) ) for result in results: imm.Log(\"<span style=\"color: #7fec7f\">Found %s at 0x%08x <\/span>\" % (searchFor.<span style=\"color: #5576D1\">replace<\/span>('\\n',' - '), result), address = result)<\/pre>\n<\/p>\n<p>Example 3 :<\/p>\n<p>If you want to use opcode directly (instead of instructions), then<\/p>\n<p>\u2013 the search looks a little bit different (no need to Assemble first)<\/p>\n<p>\u2013 you can disassemble the instruction at the found address using the Disasm() + getDisasm() functions<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\"><span style=\"color: #5576D1\">def<\/span> main(args): imm.Log(\"<span style=\"color: #7fec7f\">Started search for mov ebp,esp <\/span>\") imm.updateLog() searchFor=\"<span style=\"color: #7fec7f\">\\x8b\\xec<\/span>\" #mov ebp,esp \/ ret results=imm.Search( searchFor ) for result in results: opc = imm.Disasm( result ) opstring=opc.getDisasm() imm.Log(\"<span style=\"color: #7fec7f\">Found %s at 0x%08x <\/span>\" % (opstring, result), address = result)<\/pre>\n<p>Note : when you search through memory, it will search all process memory (loaded modules and outside loaded modules, but always limited to the memory that is used in the process). As stated earlier, searching through memory can make your CPU spike to 100%.<\/p>\n<\/p>\n<h4>Writing your own assembler\u2026<\/h4>\n<p>\u2026 is as easy as doing this :<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\">__VERSION__ = '1.0' <span style=\"color: #5576D1\">import<\/span> immlib <span style=\"color: #5576D1\">import<\/span> getopt <span style=\"color: #5576D1\">import<\/span> immutils from immutils <span style=\"color: #5576D1\">import<\/span> * imm = immlib.Debugger() <span style=\"color: #5576D1\">import<\/span> <span style=\"color: #5576D1\">re<\/span> \"<span style=\"color: #7fec7f\"><\/span>\"\" Main application \"<span style=\"color: #7fec7f\"><\/span>\"\" <span style=\"color: #5576D1\">def<\/span> main(args): <span style=\"color: #5576D1\">if<\/span> (args[0]==\"<span style=\"color: #7fec7f\">assemble<\/span>\"): <span style=\"color: #5576D1\">if<\/span> (len(args) < 2): imm.Log(\"<span style=\"color: #7fec7f\"> Usage : !plugin1 compare instructions<\/span>\") imm.Log(\"<span style=\"color: #7fec7f\"> separate multiple instructions with #<\/span>\") <span style=\"color: #5576D1\">else<\/span>: cnt=1 cmdInput=\"<span style=\"color: #7fec7f\"><\/span>\" while (cnt < len(args)): cmdInput=cmdInput+args[cnt]+\"<span style=\"color: #7fec7f\"> <\/span>\" cnt=cnt+1 cmdInput=cmdInput.<span style=\"color: #5576D1\">replace<\/span>(\"<span style=\"color: #7fec7f\">'<\/span>\",\"<span style=\"color: #7fec7f\"><\/span>\") cmdInput=cmdInput.<span style=\"color: #5576D1\">replace<\/span>('\"<span style=\"color: #7fec7f\">','') <\/span> splitter=<span style=\"color: #5576D1\">re<\/span>.compile('#') instructions=splitter.<span style=\"color: #5576D1\">split<\/span>(cmdInput) for instruct in instructions: try: assembled=imm.Assemble( instruct ) strAssembled=\"<span style=\"color: #7fec7f\"><\/span>\" for assemOpc in assembled: strAssembled = strAssembled+hex(ord(assemOpc)).<span style=\"color: #5576D1\">replace<\/span>('0x', '\\\\x') imm.Log(\"<span style=\"color: #7fec7f\"> %s = %s<\/span>\" % (instruct,strAssembled)) except: imm.Log(\"<span style=\"color: #7fec7f\"> Could not assemble %s <\/span>\" % instruct) continue<\/pre>\n<p>(I added \u201cimport re\u2019\u201d at the beginning of the script so I could use the splitter (re.compile()))<\/p>\n<p><a href=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image62.png\" target=\"_blank\" rel=\"noopener external noreferrer\" class=\"thickbox no_icon\" data-wpel-link=\"external\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px\" height=\"140\" alt=\"image\" src=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb62.png\" width=\"677\" border=\"0\" \/><\/a><\/p>\n<\/p>\n<h4>Stepping through memory<\/h4>\n<p>There may be a case where you would like to read memory from a given start location and get the bytes in memory. This can be done using the following technique :<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\"><span style=\"color: #5576D1\">if<\/span> (args[0]==\"<span style=\"color: #7fec7f\">readmem<\/span>\"): <span style=\"color: #5576D1\">if<\/span> (len(args) > 1): imm.Log(\"<span style=\"color: #7fec7f\">Reading 8 bytes of memory at %s <\/span>\" % args[1]) cnt=0 memloc=int(args[1],16) while (cnt < 8): memchar = imm.readMemory(memloc+cnt,1) memchar2 = hex(ord(memchar)).<span style=\"color: #5576D1\">replace<\/span>('0x','') imm.Log(\"<span style=\"color: #7fec7f\">Byte %d : %s<\/span>\" % (cnt+1,memchar2)) cnt=cnt+1<\/pre>\n<p>The readMemory() method requires 2 arguments : the location where you want to read, and the amount of bytes to read.<\/p>\n<p><a href=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image65.png\" target=\"_blank\" rel=\"noopener external noreferrer\" class=\"thickbox no_icon\" data-wpel-link=\"external\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px\" height=\"150\" alt=\"image\" src=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb65.png\" width=\"317\" border=\"0\" \/><\/a><\/p>\n<\/p>\n<h3>Registers<\/h3>\n<p>Getting access to the registers is pretty straightforward too :<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\">regs = imm.getRegs() for reg in regs: imm.Log(\"<span style=\"color: #7fec7f\">Register %s : 0x%08X <\/span>\" % (reg,regs[reg]))<\/pre>\n<\/p>\n<h3>SEH chain<\/h3>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\"><span style=\"color: #5576D1\">def<\/span> main(args): <span style=\"color: #5576D1\">if<\/span> (args[0]==\"<span style=\"color: #7fec7f\">sehchain<\/span>\"): thissehchain=imm.getSehChain() sehtable=imm.createTable('SEH Chain',['Address','Value']) for chainentry in thissehchain: sehtable.<span style=\"color: #5576D1\">add<\/span>(0,(\"<span style=\"color: #7fec7f\">0x%08x<\/span>\"%(chainentry[0]),(\"<span style=\"color: #7fec7f\">%08x<\/span>\"%(chainentry[1]))))<\/pre>\n<p><a href=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image64.png\" target=\"_blank\" rel=\"noopener external noreferrer\" class=\"thickbox no_icon\" data-wpel-link=\"external\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px\" height=\"189\" alt=\"image\" src=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb64.png\" width=\"258\" border=\"0\" \/><\/a><\/p>\n<\/p>\n<h3>Address & Module properties<\/h3>\n<p>When your script is searching through memory, and it retrieves an address, there may be certain things you want to know about the address:<\/p>\n<p>\u2013 does it belong to a module and if so, which one ?<\/p>\n<p>\u2013 what is the baseaddress and size of the module ?<\/p>\n<p>\u2013 is this module compiled with safeseh or not ?<\/p>\n<p>\u2013 is this module alsr aware or not ?<\/p>\n<p>\u2013 what is the access level at a given memory location ?<\/p>\n<p>Very good questions, and all of them can be solved in your script<\/p>\n<p><em>We\u2019ll pretend you have performed a search, and \u201cresult\u201d is an element in the search results array.<\/em><\/p>\n<p><em><\/em><\/p>\n<h4>See if a an address belongs to a module<\/h4>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\"><span style=\"color: #5576D1\">module<\/span> = imm.findModule(result) <span style=\"color: #5576D1\">if<\/span> not <span style=\"color: #5576D1\">module<\/span>: <span style=\"color: #5576D1\">module<\/span>=\"<span style=\"color: #7fec7f\">none<\/span>\" <span style=\"color: #5576D1\">else<\/span>: <span style=\"color: #5576D1\">module<\/span>=<span style=\"color: #5576D1\">module<\/span>[0].<span style=\"color: #5576D1\">lower<\/span>()<\/pre>\n<\/p>\n<h4>Module baseaddress and size<\/h4>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\">modbase=<span style=\"color: #5576D1\">module<\/span>.getBaseAddress() modsize=<span style=\"color: #5576D1\">module<\/span>.getSize() modtop=modbase+modsize <\/pre>\n<\/p>\n<h4>Is this module compiled with safeseh ?<\/h4>\n<p>(this piece of code requires you to \u201cimport struct\u201d at the beginning of the code)<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\"><span style=\"color: #5576D1\">module<\/span> = imm.findModule(result) # <span style=\"color: #5576D1\">mod<\/span>=imm.getModule(<span style=\"color: #5576D1\">module<\/span>[0]) mzbase=<span style=\"color: #5576D1\">mod<\/span>.getBaseAddress() peoffset=struct.<span style=\"color: #5576D1\">unpack<\/span>('<L',imm.readMemory(mzbase+0x3c,4))[0] pebase=mzbase+peoffset <span style=\"color: #5576D1\">flags<\/span>=struct.<span style=\"color: #5576D1\">unpack<\/span>('<H',imm.readMemory(pebase+0x5e,2))[0] numberofentries=struct.<span style=\"color: #5576D1\">unpack<\/span>('<L',imm.readMemory(pebase+0x74,4))[0] <span style=\"color: #5576D1\">if<\/span> numberofentries>10: sectionaddress,sectionsize=struct.<span style=\"color: #5576D1\">unpack<\/span>('<LL',imm.readMemory(pebase+0x78+8*10,8)) sectionaddress+=mzbase <span style=\"color: #5576D1\">data<\/span>=struct.<span style=\"color: #5576D1\">unpack<\/span>('<L',imm.readMemory(sectionaddress,4))[0] condition=(sectionsize!=0) and ((sectionsize==0x40) or (sectionsize==<span style=\"color: #5576D1\">data<\/span>)) <span style=\"color: #5576D1\">if<\/span> condition==False: imm.Log(\"<span style=\"color: #7fec7f\">Module %s is not safeseh protected<\/span>\" % <span style=\"color: #5576D1\">module<\/span>[0]) continue<\/pre>\n<\/p>\n<h4>Is this module aslr aware or not ?<\/h4>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\"><span style=\"color: #5576D1\">module<\/span> = imm.findModule(result) <span style=\"color: #5576D1\">mod<\/span>=imm.getModule(<span style=\"color: #5576D1\">module<\/span>[0]) mzbase=<span style=\"color: #5576D1\">mod<\/span>.getBaseAddress() peoffset=struct.<span style=\"color: #5576D1\">unpack<\/span>('<L',imm.readMemory(mzbase+0x3c,4))[0] pebase=mzbase+peoffset <span style=\"color: #5576D1\">flags<\/span>=struct.<span style=\"color: #5576D1\">unpack<\/span>('<H',imm.readMemory(pebase+0x5e,2))[0] <span style=\"color: #5576D1\">if<\/span> (<span style=\"color: #5576D1\">flags<\/span>&0x0040)==0: imm.Log(\"<span style=\"color: #7fec7f\">Module %s is not aslr aware<\/span>\" % <span style=\"color: #5576D1\">module<\/span>[0])<\/pre>\n<h4>Access level<\/h4>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\">page = imm.getMemoryPagebyAddress( result ) access = page.getAccess( human = True ) imm.Log(\"<span style=\"color: #7fec7f\">Access : %s<\/span>\" % access)<\/pre>\n<\/p>\n<h4>Combined into one script :<\/h4>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\"><span style=\"color: #5576D1\">if<\/span> (args[0]==\"<span style=\"color: #7fec7f\">test<\/span>\"): imm.Log(\"<span style=\"color: #7fec7f\">Started search for mov ebp,esp <\/span>\") imm.updateLog() searchFor=\"<span style=\"color: #7fec7f\">\\x8b\\xec<\/span>\" #mov ebp,esp \/ ret results=imm.Search( searchFor ) for result in results: opc = imm.Disasm( result ) opstring=opc.getDisasm() <span style=\"color: #5576D1\">module<\/span> = imm.findModule(result) <span style=\"color: #5576D1\">if<\/span> not <span style=\"color: #5576D1\">module<\/span>: <span style=\"color: #5576D1\">module<\/span>=\"<span style=\"color: #7fec7f\">none<\/span>\" <span style=\"color: #5576D1\">else<\/span>: page = imm.getMemoryPagebyAddress( result ) access = page.getAccess( human = True ) <span style=\"color: #5576D1\">mod<\/span>=imm.getModule(<span style=\"color: #5576D1\">module<\/span>[0]) mzbase=<span style=\"color: #5576D1\">mod<\/span>.getBaseAddress() peoffset=struct.<span style=\"color: #5576D1\">unpack<\/span>('<L',imm.readMemory(mzbase+0x3c,4))[0] pebase=mzbase+peoffset <span style=\"color: #5576D1\">flags<\/span>=struct.<span style=\"color: #5576D1\">unpack<\/span>('<H',imm.readMemory(pebase+0x5e,2))[0] numberofentries=struct.<span style=\"color: #5576D1\">unpack<\/span>('<L',imm.readMemory(pebase+0x74,4))[0] <span style=\"color: #5576D1\">if<\/span> numberofentries>10: sectionaddress,sectionsize=struct.<span style=\"color: #5576D1\">unpack<\/span>('<LL',imm.readMemory(pebase+0x78+8*10,8)) sectionaddress+=mzbase <span style=\"color: #5576D1\">data<\/span>=struct.<span style=\"color: #5576D1\">unpack<\/span>('<L',imm.readMemory(sectionaddress,4))[0] condition=(sectionsize!=0) and ((sectionsize==0x40) or (sectionsize==<span style=\"color: #5576D1\">data<\/span>)) <span style=\"color: #5576D1\">if<\/span> condition==False: imm.Log(\"<span style=\"color: #7fec7f\">Module %s is not safeseh protected<\/span>\" % <span style=\"color: #5576D1\">module<\/span>[0],highlight=1) continue <span style=\"color: #5576D1\">if<\/span> (<span style=\"color: #5576D1\">flags<\/span>&0x0040)==0: extrastring=\"<span style=\"color: #7fec7f\">not ASLR aware<\/span>\" <span style=\"color: #5576D1\">else<\/span>: extrastring=\"<span style=\"color: #7fec7f\">ASLR protected<\/span>\" imm.Log(\"<span style=\"color: #7fec7f\">Found %s at 0x%08x - [module %s] - access %s - ASLR : %s <\/span>\" % (opstring, result,<span style=\"color: #5576D1\">module<\/span>[0],access,extrastring), address = result) <\/pre>\n<\/p>\n<h4>Debugged application : Name and path<\/h4>\n<p>If you want to (dynamically) filter out the name of the loaded executable (and get the path as well), you can use the following methods :<\/p>\n<pre style=\"border-right: #cecece 1px solid; padding-right: 5px; border-top: #cecece 1px solid; padding-left: 5px; min-height: 40px; padding-bottom: 5px; overflow: auto; border-left: #cecece 1px solid; width: 650px; padding-top: 5px; border-bottom: #cecece 1px solid; background-color: #333333\"><span style=\"color: #5576D1\">name<\/span>=imm.getDebuggedName() imm.Log(\"<span style=\"color: #7fec7f\">Name : %s<\/span>\" % <span style=\"color: #5576D1\">name<\/span>) me=imm.getModule(<span style=\"color: #5576D1\">name<\/span>) <span style=\"color: #5576D1\">path<\/span>=me.getPath() imm.Log(\"<span style=\"color: #7fec7f\">Path : %s<\/span>\" % <span style=\"color: #5576D1\">path<\/span>)<\/pre>\n<\/p>\n<h3>Impact of upgrading to Immunity Debugger v1.74 and above<\/h3>\n<p>Immunity plans to fix some method\/attribute inconsistencies (especially with uppercase\/lowercase characters in the function\/method names) in a newer version of Immunity (and the Immunity libraries). As a result of that, you may have to fix your PyCommand in order to make it work with newer versions of the debugger.<\/p>\n<p>This is an overview of what you probably will need to fix :<\/p>\n<table bordercolor=\"#000000\" bordercolordark=\"#ffffff\" width=\"60%\" bordercolorlight=\"#ffffff\" border=\"1\">\n<tbody>\n<tr>\n<td><strong>Current v1.73<\/strong><\/td>\n<td><strong>newer versions<\/strong><\/td>\n<\/tr>\n<tr>\n<td>.Log<\/td>\n<td>.log<\/td>\n<\/tr>\n<tr>\n<td>.Assemble<\/td>\n<td>.assemble<\/td>\n<\/tr>\n<tr>\n<td>.Disassemble<\/td>\n<td>.disassemble<\/td>\n<\/tr>\n<tr>\n<td>.Search<\/td>\n<td>.search<\/td>\n<\/tr>\n<tr>\n<td>.getMemoryPagebyAddress<\/td>\n<td>.getMemoryPageByAddress<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/p>\n<h3>Final words<\/h3>\n<p>This reference is far from complete and there is a lot more you can do with the Immunity API. I only wanted to give you a head start if you want to build your own PyCommands.<\/p>\n<p>If you have built your own new PyCommand, share it with others \u2013 I\u2019m sure other people can benefit from your work too.<\/p>\n<p>&#160;<\/p>\n<h3>Useful Links<\/h3>\n<p><a href=\"https:\/\/web.archive.org\/web\/20140717055051\/https:\/\/tuts4you.com\/download.php?list.72\">http:\/\/www.tuts4you.com\/download.php?list.72<\/a><\/p>\n<p><a title=\"http:\/\/www.defcon.org\/images\/defcon-15\/dc15-presentations\/dc-15-gomez.pdf\" href=\"http:\/\/www.defcon.org\/images\/defcon-15\/dc15-presentations\/dc-15-gomez.pdf\">http:\/\/www.defcon.org\/images\/defcon-15\/dc15-presentations\/dc-15-gomez.pdf<\/a><\/p>\n<p><a title=\"http:\/\/www.abysssec.com\/blog\/2010\/01\/immunity-debugger-pedetect-and-the-art-of-signature-generation\/\" href=\"https:\/\/web.archive.org\/web\/20110827224711\/http:\/\/www.abysssec.com:80\/blog\/2010\/01\/immunity-debugger-pedetect-and-the-art-of-signature-generation\/\">http:\/\/www.abysssec.com\/blog\/2010\/01\/immunity-debugger-pedetect-and-the-art-of-signature-generation\/<\/a><\/p>\n<p>http:\/\/beist.org\/research\/public\/immunity1\/imm_present_jff.pdf<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When I started Win32 exploit development many years ago, my preferred debugger at the time was WinDbg (and some Olly). While Windbg is a great and fast debugger, I quickly figured out that some additional\/external tools were required to improve my exploit development experience. Despite the fact that the command line oriented approach in windbg &hellip; <a href=\"https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> \"Starting to write Immunity Debugger PyCommands : my cheatsheet\"<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[3708,957,244,373,127],"tags":[3733,2802,2576,2128,2124,1978,1933,1478],"class_list":["post-2802","post","type-post","status-publish","format-standard","hentry","category-debugging","category-development","category-exploit-writing-tutorials","category-scripts","category-security","tag-exploit-development-tutorial","tag-mona-py","tag-debugging","tag-immunity-debugger","tag-debugger","tag-python","tag-pycommand","tag-plugin"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Starting to write Immunity Debugger PyCommands : my cheatsheet - Corelan | Exploit Development &amp; Vulnerability Research<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Starting to write Immunity Debugger PyCommands : my cheatsheet - Corelan | Exploit Development &amp; Vulnerability Research\" \/>\n<meta property=\"og:description\" content=\"When I started Win32 exploit development many years ago, my preferred debugger at the time was WinDbg (and some Olly). While Windbg is a great and fast debugger, I quickly figured out that some additional\/external tools were required to improve my exploit development experience. Despite the fact that the command line oriented approach in windbg &hellip; Continue reading &quot;Starting to write Immunity Debugger PyCommands : my cheatsheet&quot;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/\" \/>\n<meta property=\"og:site_name\" content=\"Corelan | Exploit Development &amp; Vulnerability Research\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/corelanconsulting\" \/>\n<meta property=\"article:published_time\" content=\"2010-01-26T22:03:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-03-22T09:15:58+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb52.png\" \/>\n<meta name=\"author\" content=\"corelanc0d3r\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@corelanc0d3r\" \/>\n<meta name=\"twitter:site\" content=\"@corelanc0d3r\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"TechArticle\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2010\\\/01\\\/26\\\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2010\\\/01\\\/26\\\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\\\/\"},\"author\":{\"name\":\"corelanc0d3r\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#\\\/schema\\\/person\\\/3be5542b9b0a0787893db83a5ad68e8f\"},\"headline\":\"Starting to write Immunity Debugger PyCommands : my cheatsheet\",\"datePublished\":\"2010-01-26T22:03:00+00:00\",\"dateModified\":\"2026-03-22T09:15:58+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2010\\\/01\\\/26\\\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\\\/\"},\"wordCount\":2462,\"publisher\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2010\\\/01\\\/26\\\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.corelan.be\\\/wp-content\\\/uploads\\\/2010\\\/01\\\/image_thumb52.png\",\"keywords\":[\"exploit development tutorial\",\"mona.py\",\"debugging\",\"immunity debugger\",\"debugger\",\"python\",\"pycommand\",\"plugin\"],\"articleSection\":[\"Debugging\",\"Development\",\"Exploit Writing Tutorials\",\"Scripts\",\"Security\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2010\\\/01\\\/26\\\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\\\/\",\"url\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2010\\\/01\\\/26\\\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\\\/\",\"name\":\"Starting to write Immunity Debugger PyCommands : my cheatsheet - Corelan | Exploit Development &amp; Vulnerability Research\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2010\\\/01\\\/26\\\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2010\\\/01\\\/26\\\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.corelan.be\\\/wp-content\\\/uploads\\\/2010\\\/01\\\/image_thumb52.png\",\"datePublished\":\"2010-01-26T22:03:00+00:00\",\"dateModified\":\"2026-03-22T09:15:58+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2010\\\/01\\\/26\\\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2010\\\/01\\\/26\\\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2010\\\/01\\\/26\\\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.corelan.be\\\/wp-content\\\/uploads\\\/2010\\\/01\\\/image_thumb52.png\",\"contentUrl\":\"https:\\\/\\\/www.corelan.be\\\/wp-content\\\/uploads\\\/2010\\\/01\\\/image_thumb52.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/2010\\\/01\\\/26\\\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.corelan.be\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Starting to write Immunity Debugger PyCommands : my cheatsheet\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#website\",\"url\":\"https:\\\/\\\/www.corelan.be\\\/\",\"name\":\"Corelan CyberSecurity Research\",\"description\":\"Corelan publishes in-depth tutorials on exploit development, Windows exploitation, vulnerability research, heap internals, reverse engineering and security tooling used by professionals worldwide.\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.corelan.be\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#organization\",\"name\":\"Corelan CyberSecurity Research\",\"url\":\"https:\\\/\\\/www.corelan.be\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.corelan.be\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/corelanlogo2_small-20.png\",\"contentUrl\":\"https:\\\/\\\/www.corelan.be\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/corelanlogo2_small-20.png\",\"width\":200,\"height\":200,\"caption\":\"Corelan CyberSecurity Research\"},\"image\":{\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/corelanconsulting\",\"https:\\\/\\\/x.com\\\/corelanc0d3r\",\"https:\\\/\\\/x.com\\\/corelanconsulting\",\"https:\\\/\\\/instagram.com\\\/corelanconsult\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.corelan.be\\\/#\\\/schema\\\/person\\\/3be5542b9b0a0787893db83a5ad68e8f\",\"name\":\"corelanc0d3r\",\"pronouns\":\"he\\\/him\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3783bed6acd72d7fa5bb2387d88acbb9a3403e7cada60b2037e1cbb74ad451f9?s=96&d=mm&r=x\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3783bed6acd72d7fa5bb2387d88acbb9a3403e7cada60b2037e1cbb74ad451f9?s=96&d=mm&r=x\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3783bed6acd72d7fa5bb2387d88acbb9a3403e7cada60b2037e1cbb74ad451f9?s=96&d=mm&r=x\",\"caption\":\"corelanc0d3r\"},\"description\":\"Peter Van Eeckhoutte is the founder of Corelan and a globally recognized expert in exploit development and vulnerability research. With over two decades in IT security, he built Corelan into a respected platform for deep technical research, hands-on training, and knowledge sharing. Known for his influential exploit development tutorials, tools, and real-world training, Peter combines a strong research mindset with a passion for education\u2014helping security professionals understand not just how exploits work, but why.\",\"sameAs\":[\"https:\\\/\\\/www.corelan-training.com\",\"https:\\\/\\\/instagram.com\\\/corelanc0d3r\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/petervaneeckhoutte\\\/\",\"https:\\\/\\\/x.com\\\/corelanc0d3r\"],\"url\":\"https:\\\/\\\/www.corelan.be\\\/index.php\\\/author\\\/admin0\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Starting to write Immunity Debugger PyCommands : my cheatsheet - Corelan | Exploit Development &amp; Vulnerability Research","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/","og_locale":"en_US","og_type":"article","og_title":"Starting to write Immunity Debugger PyCommands : my cheatsheet - Corelan | Exploit Development &amp; Vulnerability Research","og_description":"When I started Win32 exploit development many years ago, my preferred debugger at the time was WinDbg (and some Olly). While Windbg is a great and fast debugger, I quickly figured out that some additional\/external tools were required to improve my exploit development experience. Despite the fact that the command line oriented approach in windbg &hellip; Continue reading \"Starting to write Immunity Debugger PyCommands : my cheatsheet\"","og_url":"https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/","og_site_name":"Corelan | Exploit Development &amp; Vulnerability Research","article_publisher":"https:\/\/www.facebook.com\/corelanconsulting","article_published_time":"2010-01-26T22:03:00+00:00","article_modified_time":"2026-03-22T09:15:58+00:00","og_image":[{"url":"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb52.png","type":"","width":"","height":""}],"author":"corelanc0d3r","twitter_card":"summary_large_image","twitter_creator":"@corelanc0d3r","twitter_site":"@corelanc0d3r","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"TechArticle","@id":"https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/#article","isPartOf":{"@id":"https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/"},"author":{"name":"corelanc0d3r","@id":"https:\/\/www.corelan.be\/#\/schema\/person\/3be5542b9b0a0787893db83a5ad68e8f"},"headline":"Starting to write Immunity Debugger PyCommands : my cheatsheet","datePublished":"2010-01-26T22:03:00+00:00","dateModified":"2026-03-22T09:15:58+00:00","mainEntityOfPage":{"@id":"https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/"},"wordCount":2462,"publisher":{"@id":"https:\/\/www.corelan.be\/#organization"},"image":{"@id":"https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/#primaryimage"},"thumbnailUrl":"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb52.png","keywords":["exploit development tutorial","mona.py","debugging","immunity debugger","debugger","python","pycommand","plugin"],"articleSection":["Debugging","Development","Exploit Writing Tutorials","Scripts","Security"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/","url":"https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/","name":"Starting to write Immunity Debugger PyCommands : my cheatsheet - Corelan | Exploit Development &amp; Vulnerability Research","isPartOf":{"@id":"https:\/\/www.corelan.be\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/#primaryimage"},"image":{"@id":"https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/#primaryimage"},"thumbnailUrl":"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb52.png","datePublished":"2010-01-26T22:03:00+00:00","dateModified":"2026-03-22T09:15:58+00:00","breadcrumb":{"@id":"https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/#primaryimage","url":"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb52.png","contentUrl":"https:\/\/www.corelan.be\/wp-content\/uploads\/2010\/01\/image_thumb52.png"},{"@type":"BreadcrumbList","@id":"https:\/\/www.corelan.be\/index.php\/2010\/01\/26\/starting-to-write-immunity-debugger-pycommands-my-cheatsheet\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.corelan.be\/"},{"@type":"ListItem","position":2,"name":"Starting to write Immunity Debugger PyCommands : my cheatsheet"}]},{"@type":"WebSite","@id":"https:\/\/www.corelan.be\/#website","url":"https:\/\/www.corelan.be\/","name":"Corelan CyberSecurity Research","description":"Corelan publishes in-depth tutorials on exploit development, Windows exploitation, vulnerability research, heap internals, reverse engineering and security tooling used by professionals worldwide.","publisher":{"@id":"https:\/\/www.corelan.be\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.corelan.be\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.corelan.be\/#organization","name":"Corelan CyberSecurity Research","url":"https:\/\/www.corelan.be\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.corelan.be\/#\/schema\/logo\/image\/","url":"https:\/\/www.corelan.be\/wp-content\/uploads\/2026\/03\/corelanlogo2_small-20.png","contentUrl":"https:\/\/www.corelan.be\/wp-content\/uploads\/2026\/03\/corelanlogo2_small-20.png","width":200,"height":200,"caption":"Corelan CyberSecurity Research"},"image":{"@id":"https:\/\/www.corelan.be\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/corelanconsulting","https:\/\/x.com\/corelanc0d3r","https:\/\/x.com\/corelanconsulting","https:\/\/instagram.com\/corelanconsult"]},{"@type":"Person","@id":"https:\/\/www.corelan.be\/#\/schema\/person\/3be5542b9b0a0787893db83a5ad68e8f","name":"corelanc0d3r","pronouns":"he\/him","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/3783bed6acd72d7fa5bb2387d88acbb9a3403e7cada60b2037e1cbb74ad451f9?s=96&d=mm&r=x","url":"https:\/\/secure.gravatar.com\/avatar\/3783bed6acd72d7fa5bb2387d88acbb9a3403e7cada60b2037e1cbb74ad451f9?s=96&d=mm&r=x","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/3783bed6acd72d7fa5bb2387d88acbb9a3403e7cada60b2037e1cbb74ad451f9?s=96&d=mm&r=x","caption":"corelanc0d3r"},"description":"Peter Van Eeckhoutte is the founder of Corelan and a globally recognized expert in exploit development and vulnerability research. With over two decades in IT security, he built Corelan into a respected platform for deep technical research, hands-on training, and knowledge sharing. Known for his influential exploit development tutorials, tools, and real-world training, Peter combines a strong research mindset with a passion for education\u2014helping security professionals understand not just how exploits work, but why.","sameAs":["https:\/\/www.corelan-training.com","https:\/\/instagram.com\/corelanc0d3r","https:\/\/www.linkedin.com\/in\/petervaneeckhoutte\/","https:\/\/x.com\/corelanc0d3r"],"url":"https:\/\/www.corelan.be\/index.php\/author\/admin0\/"}]}},"views":62228,"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/posts\/2802","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/comments?post=2802"}],"version-history":[{"count":5,"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/posts\/2802\/revisions"}],"predecessor-version":[{"id":17188,"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/posts\/2802\/revisions\/17188"}],"wp:attachment":[{"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/media?parent=2802"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/categories?post=2802"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.corelan.be\/index.php\/wp-json\/wp\/v2\/tags?post=2802"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}