{"id":17,"date":"2007-07-12T16:30:42","date_gmt":"2007-07-12T20:30:42","guid":{"rendered":"http:\/\/www.ragestorm.net\/blogs\/?p=17"},"modified":"2007-07-12T16:31:14","modified_gmt":"2007-07-12T20:31:14","slug":"hot-patching-detouring","status":"publish","type":"post","link":"https:\/\/www.ragestorm.net\/blogs\/?p=17","title":{"rendered":"Hot Patching (\/Detouring)"},"content":{"rendered":"<p>Hot Patching is a nice feature which lets you apply a patch in-memory to affect the required code immediately. This is good as long as you can&#8217;t restart your system to do the on-disk patching. Since there are times that you can&#8217;t allow to restart your computer, probably only in servers&#8230;<\/p>\n<p>Well speaking technically about Hot Patching, if you happen to see how code is generated in MS files, for instance, you can always see the 5 CC&#8217;s in a row before every function and then the function will begin with the infamous MOV EDI, EDI.<\/p>\n<p>It looks something like this:<\/p>\n<p>0005951e (01) 90\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0NOP<br \/>\n0005951f (01) 90\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 NOP<br \/>\n00059520 (01) 90\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 NOP<br \/>\n00059521 (01) 90\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 NOP<br \/>\n00059522 (01) 90\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 NOP<br \/>\n00059523 (02) 8bff\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 MOV EDI, EDI<br \/>\n00059525 (01) 55\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 PUSH EBP<br \/>\n00059526 (02) 8bec\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 MOV EBP, ESP<\/p>\n<p>This is a real example, but this time it uses NOP&#8217;s instead of INT3&#8217;s&#8230; It doesn&#8217;t really matter, that piece of padding code isn&#8217;t really executed.<br \/>\nFirst things first &#8211; So why the MOV EDI, EDI is really executed?<br \/>\nSo before I answer directly to this question, I will just say that when you want to patch the function, you will make a detour. So instead of patching a few bytes here and there, you will probably load a new whole copy of the patched and fixed function to a new region in the memory. This will be easier than specific spots patching&#8230; And then you will want this new code to run instead of the old one. Now you have two options to patch <em>all<\/em> callers to this function, which is a crazy thing to do. Or the more popular way-\u00a0the trick comes in, the MOV EDI, EDI is used as a pseudo NOP, and it is executed on purpose every time the function runs. So when time comes and you apply the patch you can simply override this instruction with a short JMP instruction which takes 2 bytes as well. The jump instruction will jump 5 bytes backward to the beginning of the padding precisely before the patched function. So why 5 bytes of padding and not less or more? This is an easy one, in 5 bytes you can jump anywhere in the address space of 32 bits. Thus, no matter where your new patched function lies in memory you can jump to it. So the 5 bytes will be patched to contain a long JMP instruction. The offset of the long JMP will be calculated once as a relative offset.<\/p>\n<p>Well, actually I didn&#8217;t really answer the first question yet. But now that you got a better understanding of this mechanism I really can. The thing is, that in old times the perfect patchers had to disassemble the beginning of the patched function in order to see where it can replace a few instructions to put the 5 bytes long JMP. So it transfers control to you in the beginning of the original function and when you are done, you run the overriden instruction, but as <em>whole <\/em>instructions(!) and then continue executing that same function from the place you finished overriding it.<\/p>\n<p>Here&#8217;s some example, the first instruction for the sake of conversation takes 3 bytes and then the second instruction takes\u00a03 bytes too. Now if you put the long JMP instruction\u00a0at the first byte of the function and then you want to continue execution after you got control at offset 5, you will be out of synchronization and run incorrect code, because you are supposed to continue execution from offset 6&#8230; Eventually it will crash, probably for a access-violation exception.<\/p>\n<p>So now instead of having all this headache, you know that you can <strong>safely<\/strong> change the first 2 bytes, to a short JMP and it will always work no matter what.<\/p>\n<p>Another crazy reason for this new way is because say the patched function can run in a few threads at the same time. Now think that you patched the first 5 bytes, and then a different thread start running at offset 3 (because it already ran the first instruction, it just continue normally, but with <em>changed<\/em> code), then bam&#8230; you broke the instruction&#8230;<\/p>\n<p>\u00a0The reason for using the specific MOV instruction is understood, since it&#8217;s a pseudo NOP, it doesn&#8217;t really affect (although it is not a real NOP) the CPU context but the program counter. And EDI, was chosen to my <em>guess<\/em>, because it makes the second byte of the instruction as 0xFF when both operands are EDI, like in this case. And yet there is no specific reason that I can come up with.<\/p>\n<p>You can see that in two memcpy&#8217;s for the matter, you can detour a function successfuly without any potential problems. Piece of cake. The problem is that not all files support this feature yet, thus sometimes you still have to stick to the old methods and find a generic solution, like I did in ZERT&#8217;s patches&#8230;but that&#8217;s another story.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hot Patching is a nice feature which lets you apply a patch in-memory to affect the required code immediately. This is good as long as you can&#8217;t restart your system to do the on-disk patching. Since there are times that you can&#8217;t allow to restart your computer, probably only in servers&#8230; Well speaking technically about [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","jetpack_publicize_message":""},"categories":[5,19,13,14],"tags":[],"jetpack_featured_media_url":"","jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pbWKd-h","_links":{"self":[{"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/posts\/17"}],"collection":[{"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=17"}],"version-history":[{"count":0,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/posts\/17\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=17"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=17"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=17"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}