<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8237815422107266951</id><updated>2024-08-30T12:29:40.638+02:00</updated><category term="code"/><category term="assembly"/><category term="android"/><category term="cpu"/><category term="hacks"/><category term="math"/><category term="windows"/><category term="automation"/><category term="compression"/><category term="decompilation"/><category term="graphics"/><category term="malware"/><category term="poker"/><category term="python"/><category term="reverse engineering"/><category term="security"/><category term="sudoku"/><title type='text'>MiscellaneouZ</title><subtitle type='html'>Code, hacks, security, RE, misc...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>17</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8237815422107266951.post-4919734360834758043</id><published>2012-11-26T18:37:00.000+01:00</published><updated>2012-11-26T18:38:58.572+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="android"/><category scheme="http://www.blogger.com/atom/ns#" term="decompilation"/><category scheme="http://www.blogger.com/atom/ns#" term="reverse engineering"/><category scheme="http://www.blogger.com/atom/ns#" term="security"/><title type='text'>New venture - Android decompiler</title><content type='html'>I&#39;m currently working on &lt;a href=&quot;http://www.android-decompiler.com/#features&quot;&gt;JEB&lt;/a&gt;, an interactive Android app decompiler for security analysts and reverse engineers.&lt;br /&gt;
&lt;br /&gt;
JEB should be out late December/early Jan. Check out &lt;a href=&quot;http://www.android-decompiler.com/&quot;&gt;www.android-decompiler.com&lt;/a&gt; to get all the details.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkU5j8YAdMPYD6mut194LTQgcBOH7ra2o5JQswB0_v61TLdYSBMVJmNz6mwZebC72TdXvx7disU9PmJ0iNuyJEQWSTynUDb-NsE-EAgopE9Pt9v5jVAITIiNL5TtnJRolofUg-bNk4786n/s1600/jeb-simplview-comment.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;192&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkU5j8YAdMPYD6mut194LTQgcBOH7ra2o5JQswB0_v61TLdYSBMVJmNz6mwZebC72TdXvx7disU9PmJ0iNuyJEQWSTynUDb-NsE-EAgopE9Pt9v5jVAITIiNL5TtnJRolofUg-bNk4786n/s320/jeb-simplview-comment.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/4919734360834758043/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/8237815422107266951/4919734360834758043' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/4919734360834758043'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/4919734360834758043'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/2012/11/new-venture.html' title='New venture - Android decompiler'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkU5j8YAdMPYD6mut194LTQgcBOH7ra2o5JQswB0_v61TLdYSBMVJmNz6mwZebC72TdXvx7disU9PmJ0iNuyJEQWSTynUDb-NsE-EAgopE9Pt9v5jVAITIiNL5TtnJRolofUg-bNk4786n/s72-c/jeb-simplview-comment.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8237815422107266951.post-910679831173218955</id><published>2011-11-28T00:08:00.001+01:00</published><updated>2011-11-28T09:09:01.684+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="code"/><category scheme="http://www.blogger.com/atom/ns#" term="graphics"/><category scheme="http://www.blogger.com/atom/ns#" term="math"/><title type='text'>Visualizing lemniscates and Cassinian curves</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;&lt;p class=&quot;MsoNormal&quot;&gt;Last night was fun. I found a USB stick I haven&#39;t used in years and couldn’t resist browsing its content. My excitement rose when I retrieved - among various other juicy and less juicy pieces of data, mostly dating back from the college era – an archive containing many old C programs. I stumbled upon this piece of code &lt;i&gt;/rambling_begins&lt;/i&gt; I wrote at a time my friends and I were venerating Brian Greene et al. and our bible was the Elegant Universe. Eventually, my friends went to study physics but did not major in cosmology. Applied physics pay the bills. String theory physicists are starving to death nowadays! /r&lt;i&gt;ambling_over.&lt;/i&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;So the idea was to visually represent &lt;b&gt;lemniscates&lt;/b&gt;.&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;Lemniscates and its derivatives are fascinating mathematical objects. (Their construction was appealing because it resembled the ellipse&#39;s.) &lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Remember that an ellipse is defined by its two centers C0, C1 and the set of points P such that dist(C0,P)+dist(C1,P) is constant:&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 267px;&quot; src=&quot;http://upload.wikimedia.org/wikipedia/commons/thumb/6/65/Ellipse_Properties_of_Directrix_and_String_Construction.svg/400px-Ellipse_Properties_of_Directrix_and_String_Construction.svg.png&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot; style=&quot;text-align: center;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; &gt;Image (c) Wikipedia&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;A lemniscate is also defined by its two centers C0, C1 and a set of points P, but this time d=dist(C0,P)*dist(C1,P) must be constant. The most famous lemniscate is &lt;b&gt;Bernouilli&lt;/b&gt;’s, where d is set to sqrt(dist(C0,C1)/2). This produces … the infinite sign:&lt;/p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPGysEk5SltZTn5OS8j71GD1SvD6xLbCTucO2wtYY2HcZ9CtOm_dLGc1FJATPSWLPDgp-E7QAjaeGYJE5nMqpXH4LihpylH3cn-zsMtQ5sZim2yPIb5Ri1sh5Dn-yw0JDRukIWrYXYfMdC/s1600/lemniscate_bernouilli.jpg&quot; onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 119px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPGysEk5SltZTn5OS8j71GD1SvD6xLbCTucO2wtYY2HcZ9CtOm_dLGc1FJATPSWLPDgp-E7QAjaeGYJE5nMqpXH4LihpylH3cn-zsMtQ5sZim2yPIb5Ri1sh5Dn-yw0JDRukIWrYXYfMdC/s320/lemniscate_bernouilli.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5679947605420260178&quot; /&gt;&lt;/a&gt;&lt;div style=&quot;text-align: center;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; &gt;Image (c) Mathcurve.com&lt;/span&gt;&lt;/div&gt;&lt;p class=&quot;MsoNormal&quot;&gt;Generalized, these lemniscates are formally called &lt;b&gt;Cassini’s ovals&lt;/b&gt;, and we can intuitively guess that greater values of d generate what look like ellipses, whereas smaller values of d generate pairs of pseudo-circles:&lt;/p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaaPr_0I7o9T9GvpK8bMtT7OEJQEdbh5Y5bV8nM2NOy8tn8srquQu6h69aBWDXa7o1GBCerDxiwAi-tiFruuHbpAdSVMgwuaUjcylecZSbycqLE9qUcCwZvny8bjzJnYsoISamFrzn9Dlf/s1600/cassini_ovals.jpg&quot; onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 175px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaaPr_0I7o9T9GvpK8bMtT7OEJQEdbh5Y5bV8nM2NOy8tn8srquQu6h69aBWDXa7o1GBCerDxiwAi-tiFruuHbpAdSVMgwuaUjcylecZSbycqLE9qUcCwZvny8bjzJnYsoISamFrzn9Dlf/s320/cassini_ovals.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5679948068818219314&quot; /&gt;&lt;/a&gt;&lt;div style=&quot;text-align: center;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; &gt;Image (c) Mathcurve.com&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now the last step was to generalize that to 3, 4 and more centers. The formal name of these beauties is &lt;b&gt;Cassinian curves&lt;/b&gt;, and they look like that:&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT2g70vQDhQS_WZ8NiZLOZRujikMbLGSj_oRydQNJf1nS8qt9g0UPx8ka5kaupDbeVGt2Y2MjFaspC-8SSAiRWxWweuq7CpImsQGbpDIIFtlratqpm12RnnYP1Pzzz7WKlq65OefmbF_RO/s1600/cassinian_curves.jpg&quot; onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 238px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT2g70vQDhQS_WZ8NiZLOZRujikMbLGSj_oRydQNJf1nS8qt9g0UPx8ka5kaupDbeVGt2Y2MjFaspC-8SSAiRWxWweuq7CpImsQGbpDIIFtlratqpm12RnnYP1Pzzz7WKlq65OefmbF_RO/s320/cassinian_curves.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5679948381461757010&quot; /&gt;&lt;/a&gt;&lt;div style=&quot;text-align: center;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: small; &quot;&gt;Image (c) Mathcurve.com&lt;/span&gt;&lt;/div&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;Back in the days, I didn’t know these objects had real names – not to mention their use in electrostatic fields analysis. I was experimenting and simply called them &lt;i&gt;generalized lemnicates&lt;/i&gt;. Anyway, below are a few of screenshots with 2 centers, 3 centers, 6 centers, and a couple of zoomed-in areas.&lt;/p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFo_iuHCXT-NSjiYBfL0k0U7M-J2n2L-JcgSBO95zq8wavQz4kJsK-8skzGqecOJMZh48WXr2fNZ_oz5TnwL4Vz4U9QJwffJApPVdLswYZ4XciuJ-4bcXO9YGspxtXMpPOXXi6da_-Wfsm/s1600/cassini_gradient_2pts.jpg&quot; onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 214px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFo_iuHCXT-NSjiYBfL0k0U7M-J2n2L-JcgSBO95zq8wavQz4kJsK-8skzGqecOJMZh48WXr2fNZ_oz5TnwL4Vz4U9QJwffJApPVdLswYZ4XciuJ-4bcXO9YGspxtXMpPOXXi6da_-Wfsm/s320/cassini_gradient_2pts.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5679949689766144642&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-9XyBTbk1MSVmjU9TgfKxrTqmEeG02LvNlrGV2UelEX0zQr_MTFAsgCbKs_YM0O03RornmdGFH1Fxn7bRWhS3fzoBXuFNp7iBkjOhO9S-tIbP8H6G3UTSq6mWDEnE6G4KnmWvInmb9aB1/s1600/cassini_gradient_3pts_center.jpg&quot; onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 320px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-9XyBTbk1MSVmjU9TgfKxrTqmEeG02LvNlrGV2UelEX0zQr_MTFAsgCbKs_YM0O03RornmdGFH1Fxn7bRWhS3fzoBXuFNp7iBkjOhO9S-tIbP8H6G3UTSq6mWDEnE6G4KnmWvInmb9aB1/s320/cassini_gradient_3pts_center.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5679949691413135906&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyLRTaY_36_MQ3iNUUg7BYWe-t2EAIRfUbO45tUOYI5JXINA1rP59BFSbI_t0f0sDVGisN62L88P3eFqgNX7vnUd1mCf-MWPhXlYXi8INBCAvsqwNsskZ5iJeYaF50n4z8Z0MTaowJK5n3/s1600/cassini_gradient_zoom1.jpg&quot; onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 246px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyLRTaY_36_MQ3iNUUg7BYWe-t2EAIRfUbO45tUOYI5JXINA1rP59BFSbI_t0f0sDVGisN62L88P3eFqgNX7vnUd1mCf-MWPhXlYXi8INBCAvsqwNsskZ5iJeYaF50n4z8Z0MTaowJK5n3/s320/cassini_gradient_zoom1.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5679949693420681698&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFvRW1PiZwH_GdIMOSzGwJncqwTWJDkTm8-h8bFNVQGGUlcui1eq97Lz7-TNL2DMg4VxIYH-ca-yN1E3kyspReZUGAQbvvFWslsugp4wvj2QbJM91OGGuCkHrv6OfOz3poP-FmXr7LD8vi/s1600/cassini_gradient_zoom2.jpg&quot; onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 234px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFvRW1PiZwH_GdIMOSzGwJncqwTWJDkTm8-h8bFNVQGGUlcui1eq97Lz7-TNL2DMg4VxIYH-ca-yN1E3kyspReZUGAQbvvFWslsugp4wvj2QbJM91OGGuCkHrv6OfOz3poP-FmXr7LD8vi/s320/cassini_gradient_zoom2.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5679949705066947250&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;The trick to get these cool gradients is to rely on the RGB implementation used by most programming frameworks. The (Red, Green, Blue) tuple is represented by 3 bytes stored in a 32-bit dword. (The high-byte can be the alpha channel, but is irrelevant in the case of raw colors.) If we define d=dist(C0,P)*dist(C1,P)*…*dist(Cn,P) and represent d as a colored pixel whose RGB value is directly proportional to d (ie, a number between 0 and 0FFFFFFh).&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;The yellow-ish separations mean that the Blue byte is about to be incremented. Of course, this depends on the number of centers and how close they are to each other: these initial conditions yield the range of value d can have within the window. With more 10 centers, very close to each other, it takes a while to get to Blue=1, therefore we can see increments of Green (at least the first 4 are clearly marked out).&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1qxqmuNlJ3ajCtH7YCttlXWNl5GiOiD2hcQqoeiAB26vlBwLx0Y0n3G364Dvtxogq5cE42znqWvYj_pqJu9OoH4u4jsTgOc2dht2_xiOEp1bnSm_ax2U1EUIHked-o1xHrwjz52ZwacQ9/s1600/cassini_gradient_blackhole.jpg&quot; onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 176px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1qxqmuNlJ3ajCtH7YCttlXWNl5GiOiD2hcQqoeiAB26vlBwLx0Y0n3G364Dvtxogq5cE42znqWvYj_pqJu9OoH4u4jsTgOc2dht2_xiOEp1bnSm_ax2U1EUIHked-o1xHrwjz52ZwacQ9/s320/cassini_gradient_blackhole.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5679949705022900002&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;I’ve attached the source and binary so you can experiment yourself. (Sorry for the Linux folks out there, it’s Windows C…)&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/910679831173218955/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/8237815422107266951/910679831173218955' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/910679831173218955'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/910679831173218955'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/2011/11/visualizing-lemniscates-and-cassinian.html' title='Visualizing lemniscates and Cassinian curves'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPGysEk5SltZTn5OS8j71GD1SvD6xLbCTucO2wtYY2HcZ9CtOm_dLGc1FJATPSWLPDgp-E7QAjaeGYJE5nMqpXH4LihpylH3cn-zsMtQ5sZim2yPIb5Ri1sh5Dn-yw0JDRukIWrYXYfMdC/s72-c/lemniscate_bernouilli.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8237815422107266951.post-4733617002989891779</id><published>2011-11-03T03:47:00.008+01:00</published><updated>2011-11-03T03:57:44.570+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="android"/><category scheme="http://www.blogger.com/atom/ns#" term="code"/><title type='text'>Raasta</title><content type='html'>I haven&#39;t posted in a very long while, mainly due to time and professional constraints. This will be fixed eventually.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Meanwhile, this atypical post is meant to let my (many, many) readers know that I recently released my first Android app: &lt;a href=&quot;https://market.android.com/details?id=com.pnfsoftware.raasta&quot;&gt;Raasta&lt;/a&gt; is a powerful, battery-friendly GPS tracker designed to fully operate in areas without data reception. You can record your progress and geolocate yourself during hikes, roadtrips or explorations. It&#39;s packed with features, including editable landmarks, custom GPS periods, KML exports, GMap overlay, etc.&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Check out the full description and download the app here: &lt;a href=&quot;https://market.android.com/details?id=com.pnfsoftware.raasta&quot;&gt;https://market.android.com/details?id=com.pnfsoftware.raasta&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Best of all: it&#39;s entirely free!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNTmr1bR9Qd0nkas07fM7bQUIt3EZ1Unduej7s-NUVxyBz_4i44knU79YMGPuhyphenhyphen0Rp7UKVsQ0iofhdUpmQJEm05WVrDboxLDhuxXsoM9ljHjGyuj3345Zb-0ryPouzWtVvlLPjayZAZhpQ/s1600/ss-320-0-0.png&quot; onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 214px; height: 320px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNTmr1bR9Qd0nkas07fM7bQUIt3EZ1Unduej7s-NUVxyBz_4i44knU79YMGPuhyphenhyphen0Rp7UKVsQ0iofhdUpmQJEm05WVrDboxLDhuxXsoM9ljHjGyuj3345Zb-0ryPouzWtVvlLPjayZAZhpQ/s320/ss-320-0-0.png&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5670596954596137282&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7gLIJeho_MvlRTOumoQwNV9aYpcnPBh3HtEe8nrLARBOU0gOSXX9n5UfcBWFbQklJ-2pzjVyEF1pk7T891_izm7FLGlqE_goMSuVNT_C9Ds-HOq1DBK40IKVEXgmGO8IlJSu-jWGSsbFS/s1600/ss-320-1-0.png&quot; onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 214px; height: 320px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7gLIJeho_MvlRTOumoQwNV9aYpcnPBh3HtEe8nrLARBOU0gOSXX9n5UfcBWFbQklJ-2pzjVyEF1pk7T891_izm7FLGlqE_goMSuVNT_C9Ds-HOq1DBK40IKVEXgmGO8IlJSu-jWGSsbFS/s320/ss-320-1-0.png&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5670597183756701890&quot; /&gt;&lt;/a&gt;&lt;br /&gt;Edit: Also, I&#39;ve decided to join the Twitter crowd. You can follow me @NicolasFalliere. Not a lot of tweets at the moment, I&#39;m still in the discovery phase :)&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/4733617002989891779/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/8237815422107266951/4733617002989891779' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/4733617002989891779'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/4733617002989891779'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/2011/11/raasta.html' title='Raasta'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNTmr1bR9Qd0nkas07fM7bQUIt3EZ1Unduej7s-NUVxyBz_4i44knU79YMGPuhyphenhyphen0Rp7UKVsQ0iofhdUpmQJEm05WVrDboxLDhuxXsoM9ljHjGyuj3345Zb-0ryPouzWtVvlLPjayZAZhpQ/s72-c/ss-320-0-0.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8237815422107266951.post-4677145576872199997</id><published>2010-01-19T22:00:00.003+01:00</published><updated>2010-01-19T22:19:49.760+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="code"/><category scheme="http://www.blogger.com/atom/ns#" term="windows"/><title type='text'>Windows 7 and XP SP3 system call tables</title><content type='html'>A short post to let you know that I&#39;ve uploaded system call tables for Windows Seven SP0 and Windows XP SP3 here:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://miscellaneouz.googlecode.com/svn/trunk/winsyscalls/winsyscall.html&quot;&gt;HTML version&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://miscellaneouz.googlecode.com/svn/trunk/winsyscalls/winsyscalls.py&quot;&gt;Python script&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://miscellaneouz.googlecode.com/svn/trunk/winsyscalls/winsyscalls.h&quot;&gt;C header file&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;The Python and C versions can easily be integrated into projects.&lt;br /&gt;&lt;br /&gt;The old tables (NT, 2K, XP, etc.) were generated based on the &lt;a href=&quot;http://www.metasploit.com/users/opcode/syscalls.html&quot;&gt;MetaSploit System Call Tables page&lt;/a&gt;, so thanks to them for that.&lt;br /&gt;&lt;br /&gt;Edit: here&#39;s a diff with Vista SP0 (a diff with SP2 would be more valuable, will do eventually):&lt;br /&gt;&lt;br /&gt;Syscalls added:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtAllocateReserveObject&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtAlpcRevokeSecurityContext&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtCreateKeyTransacted&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtCreateProfileEx&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtCreateUserProcess&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtDisableLastKnownGood&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtDrawText&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtEnableLastKnownGood&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtEnumerateTransactionObject&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtNotifyChangeSession&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtOpenKeyEx&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtOpenKeyTransacted&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtOpenKeyTransactedEx&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtQuerySecurityAttributesToken&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtQuerySystemInformationEx&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtQueueApcThreadEx&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtReplacePartitionUnit&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtSerializeBoot&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtSetIoCompletionEx&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtSetTimerEx&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtUmsThreadYield&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Syscalls removed:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtPullTransaction&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtGetMUILicenseInfo&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtClearMUILicenseInfo&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtRequestWakeupLatency&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtRollbackSavepointTransaction&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtClearAllSavepointsTransaction&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtClearSavepointTransaction&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtRequestDeviceWakeup&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtSavepointComplete&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtStartTm&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtCancelDeviceWakeupRequest&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtMarshallTransaction&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtListTransactions&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;NtSavepointTransaction&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;Seems like there&#39;s plenty to investigate (NtCreateUserProcess, NtSerializeBoot, NtReplacePartitionUnit, NtQuerySystemInformationEx, NtQueueApcThreadEx, ...).</content><link rel='replies' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/4677145576872199997/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/8237815422107266951/4677145576872199997' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/4677145576872199997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/4677145576872199997'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/2010/01/windows-7-and-xp-sp3-system-call-tables.html' title='Windows 7 and XP SP3 system call tables'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8237815422107266951.post-7294682660478059458</id><published>2010-01-10T12:34:00.000+01:00</published><updated>2010-01-10T16:30:00.962+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="assembly"/><category scheme="http://www.blogger.com/atom/ns#" term="windows"/><title type='text'>MmGetPhysicalAddress implementation tricks</title><content type='html'>MmGetPhysicalAddress is a kernel-exported API that allows converting a virtual address to a physical one.&lt;br /&gt;&lt;br /&gt;Quick reminder: Windows runs in protected (or long/IA64) mode with paging enabled, plus/minus physical address extensions enabled. The post focus on a 32-bit kernel with PAE disabled for enhanced clarity.&lt;br /&gt;&lt;br /&gt;The PDE/PTE structures for 4Kb pages are (from Intel manual):&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfU0j1km2pXlfBHMh2fV8rd-2HsJ1KS58I1mV77pYfAavL2yeVu3VvRcWUTPffWJNeoDQGiMKdpzowTu-Y-MgUDIG3rD8p_ucImIeuzzNzXI-YDiBwmwHkQmpLzlyCyJe3YVYO8DX-pSUB/s1600-h/pde_pte_4k.png&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 270px; height: 320px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfU0j1km2pXlfBHMh2fV8rd-2HsJ1KS58I1mV77pYfAavL2yeVu3VvRcWUTPffWJNeoDQGiMKdpzowTu-Y-MgUDIG3rD8p_ucImIeuzzNzXI-YDiBwmwHkQmpLzlyCyJe3YVYO8DX-pSUB/s320/pde_pte_4k.png&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5425128320410772034&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The PDE structure for 4Mb pages is:&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7eVZI2vz7T5ouinzZ6yzB8QGL34Gbyn9z_aF-W4EAnIE_eDP-P2XpqzFIxyyw3O4TE-ZxGqiffIFO0COiDOO1XTr_7RrdhA5fyTwApIOuxt-_VuxAraXmj-IXQ8GndudkuVpei-O-eUlK/s1600-h/pde_4m.png&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 194px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7eVZI2vz7T5ouinzZ6yzB8QGL34Gbyn9z_aF-W4EAnIE_eDP-P2XpqzFIxyyw3O4TE-ZxGqiffIFO0COiDOO1XTr_7RrdhA5fyTwApIOuxt-_VuxAraXmj-IXQ8GndudkuVpei-O-eUlK/s320/pde_4m.png&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5425128589882729378&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The conversion to a physical address is done internally by the hardware. No instruction implements a physical-to-virtual address conversion. When the operating system uses paging, the key to physical conversion lies in CR3. This register contains the physical address to the page-directory entries table.&lt;br /&gt;&lt;br /&gt;In order to do a virtual-to-physical converion programmatically, one needs to know where the page translation tables are located in &lt;span style=&quot;font-style: italic;&quot;&gt;virtual memory&lt;/span&gt;. When created, these pages are referenced only by their physical addresses, stored in the page-directory or page-table entries (see pictures above). This chicken&amp;amp;egg problem is solved by Windows (and most likely other x86 OSs) by reserving a range in the kernel address space for all lowest-level page-description pages (PTEs for 4Kb pages, PDEs for 4Mb pages).&lt;br /&gt;&lt;br /&gt;Let&#39;s examine how MmGetPhysicalAddress is implemented in the simplest version of a Windows XP SP3 kernel (32-bit, PAE disabled):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;.text:0042E046 ; unsigned __int64 __stdcall MmGetPhysicalAddress(unsigned int BaseAddress)&lt;br /&gt;.text:0042E046&lt;br /&gt;.text:0042E046 BaseAddress     = dword ptr  8&lt;br /&gt;.text:0042E046&lt;br /&gt;.text:0042E046                 mov     edi, edi&lt;br /&gt;.text:0042E048                 push    ebp&lt;br /&gt;.text:0042E049                 mov     ebp, esp&lt;br /&gt;.text:0042E04B                 push    esi&lt;br /&gt;.text:0042E04C                 mov     esi, [ebp+BaseAddress]&lt;br /&gt;.text:0042E04F                 mov     eax, esi&lt;br /&gt;.text:0042E051                 shr     eax, 14h&lt;br /&gt;.text:0042E054                 and     eax, 0FFCh&lt;br /&gt;.text:0042E059                 mov     ecx, [eax-3FD00000h]&lt;br /&gt;.text:0042E05F                 mov     eax, ecx&lt;br /&gt;.text:0042E061                 and     ax, 81h&lt;br /&gt;.text:0042E065                 cmp     al, 81h ;present? page size?&lt;br /&gt;.text:0042E067                 jnz     short 4Kbpage&lt;br /&gt;.text:0042E067&lt;br /&gt;.text:0042E069                 mov     eax, esi ;4Mb page&lt;br /&gt;.text:0042E06B                 shr     eax, 0Ch&lt;br /&gt;.text:0042E06E                 and     eax, 3FFh&lt;br /&gt;.text:0042E073                 shr     ecx, 0Ch&lt;br /&gt;.text:0042E076                 add     eax, ecx&lt;br /&gt;.text:0042E076&lt;br /&gt;.text:0042E078&lt;br /&gt;.text:0042E078 convert:&lt;br /&gt;.text:0042E078                 xor     ecx, ecx&lt;br /&gt;.text:0042E07A                 shld    ecx, eax, 0Ch&lt;br /&gt;.text:0042E07E                 shl     eax, 0Ch&lt;br /&gt;.text:0042E081                 and     esi, 0FFFh&lt;br /&gt;.text:0042E087                 add     eax, esi&lt;br /&gt;.text:0042E089                 mov     edx, ecx ;0&lt;br /&gt;.text:0042E089&lt;br /&gt;.text:0042E08B&lt;br /&gt;.text:0042E08B done:&lt;br /&gt;.text:0042E08B                 pop     esi&lt;br /&gt;.text:0042E08C                 pop     ebp&lt;br /&gt;.text:0042E08D                 retn    4&lt;br /&gt;.text:0042E090&lt;br /&gt;.text:0042E090 4Kbpage:&lt;br /&gt;.text:0042E090                 test    cl, 1 ;present?&lt;br /&gt;.text:0042E093                 jz      short error&lt;br /&gt;.text:0042E093&lt;br /&gt;.text:0042E095                 mov     eax, esi&lt;br /&gt;.text:0042E097                 shr     eax, 0Ah&lt;br /&gt;.text:0042E09A                 and     eax, 3FFFFCh&lt;br /&gt;.text:0042E09F                 sub     eax, 40000000h&lt;br /&gt;.text:0042E0A4                 mov     eax, [eax]&lt;br /&gt;.text:0042E0A6                 test    al, 1 ;PTE present?&lt;br /&gt;.text:0042E0A8                 jz      short error&lt;br /&gt;.text:0042E0A8&lt;br /&gt;.text:0042E0AA                 shr     eax, 0Ch&lt;br /&gt;.text:0042E0AD                 jmp     short convert&lt;br /&gt;.text:0042E0AF&lt;br /&gt;.text:0042E0AF error:&lt;br /&gt;.text:0042E0AF                 xor     eax, eax&lt;br /&gt;.text:0042E0B1                 xor     edx, edx&lt;br /&gt;.text:0042E0B3                 jmp     short done&lt;br /&gt;.text:0042E0B3&lt;br /&gt;.text:0042E0B3 _MmGetPhysicalAddress@4 endp&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Remember the VA is decomposed into 3 or 2 parts:&lt;br /&gt;- 3 parts for 4Kb pages: [10bits=PDE index / 10bits=PTE index / 12bit=Page offset]&lt;br /&gt;- 2 parts for 4Mb pages: [10bits=PDE index / 22bits=Page offset]&lt;br /&gt;&lt;br /&gt;The code first gets the PDE index*4, which is the PDE offset relative to CR3 since PDE entries are 4-byte long. This value is added to -3FD00000. The PDE offset being in [0,FFC], the result will be in [C0300000,C0300FFC]. Now, the first PDE is pointed by CR3. Which means that &lt;span style=&quot;font-weight: bold;&quot;&gt;physical_to_virtual(CR3)=C0300000, for all processes&lt;/span&gt;. The range [C0300000,C0301000[ contains the 0x400 PDEs.&lt;br /&gt;&lt;br /&gt;A comparison then checks if the page is present or not (bit0) and the function returns 0 if the page is not present. The comparison also checks for bit7; if set, this bit indicates a 4Mb page and a different, simpler code branch is executed.&lt;br /&gt;&lt;br /&gt;For a 4Kb PDE, the next 10 bits of the VA are extracted, then made a PTE offset in [0,FFC]. The offset is added to -40000000. The resulting value is in [C0000000, C03FFFFC]. This means the PTEs are in the range [C0000000, C0400000[. It&#39;s important to understand that this range is &quot;reserved&quot;; only a handful of these pages are actually mapped to physical ones, as explained below.&lt;br /&gt;&lt;br /&gt;(The physical address is then calculated by extracting the page offset part of the VA (bottom 12 or 22 bits) and adding it to the physical address of the lowest-level page in the translation hierarchy.)&lt;br /&gt;&lt;br /&gt;What&#39;s interesting in this scheme is the address range used. Let&#39;s consider a 3-level hierarchy (4Kb pages). CR3 &quot;points&quot; to C0300000, ie the first PDE is at C0300000. The PTEs go from C0000000 to C0400000: The PDE range overlaps the PTE range! And not anywhere, exactly at the 3/4th of this range; which makes sense since the 3/4th of a 32-bit address space also start at C0000000. This is not random of course: the PDEs are themselves referenced by the PTEs to allow the processor to access the [C0000000, C0400000[ range!&lt;br /&gt;&lt;br /&gt;This may seem a bit obscure, plus my explanations here are pretty poor. It&#39;s funny how explaining 30 lines of smart assembly can be so tricky... The thing to remember to understand this is that the CPU offers NO facility to do physical to virtual conversion. But to let access the kernel access the pages that allow the CPU to do this conversion internally, they must be accessible in virtual memory. And to be accessible in virtual memory, they must be referenced by themselves. This self-reference mechanism allows the implemention of MmGetPhysicalAddress.&lt;br /&gt;&lt;br /&gt;Quick lab experiment. Fire up WinDbg, local kernel debugging:&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;lkd&gt; !process 0 0 System&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;PROCESS 81bcc830  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;font-family:courier new;&quot; &gt;  DirBase: 00039000&lt;/span&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;  ObjectTable: e1000cc0  HandleCount: 244.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;Image: System&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;DirBase is the physical address of the first PDE (loaded into CR3).&lt;br /&gt;We can confirm that by check the field in the associated EPROCESS structure:&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;lkd&gt; dt _EPROCESS Pcb.DirectoryTableBase 81bcc830&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;+0x000 Pcb                    :&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;+0x018 &lt;/span&gt;&lt;span style=&quot;font-weight: bold;font-family:courier new;&quot; &gt;DirectoryTableBase     : [2] 0x39000&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now, let&#39;s get the physical address of C0300000. We use !vtop, with the PFN page for the process (39000 &gt;&gt; 12):&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;lkd&gt; !vtop 39 c0300000&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;Pdi 300 Pti 300&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;font-family:courier new;&quot; &gt;c0300000 00039000&lt;/span&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt; pfn(00039)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The result is 39000, which confirms that C0300000 maps the PDEs.&lt;br /&gt;&lt;br /&gt;You can check it for other processes, for instance WinDbg itself:&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;lkd&gt; !process 0 0 windbg.exe&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;PROCESS 81ad8410  SessionId: 0  Cid: 049c    Peb: 7ffd7000  ParentCid: 028c&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;DirBase: 00ae9000  ObjectTable: e1c446b0  HandleCount: 614.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;Image: windbg.exe&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;lkd&gt; !vtop ae9 c0300000&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;Pdi 300 Pti 300&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;c0300000 00ae9000 pfn(00ae9)&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/7294682660478059458/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/8237815422107266951/7294682660478059458' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/7294682660478059458'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/7294682660478059458'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/2009/12/mmgetphysicaladdress-implementation.html' title='MmGetPhysicalAddress implementation tricks'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfU0j1km2pXlfBHMh2fV8rd-2HsJ1KS58I1mV77pYfAavL2yeVu3VvRcWUTPffWJNeoDQGiMKdpzowTu-Y-MgUDIG3rD8p_ucImIeuzzNzXI-YDiBwmwHkQmpLzlyCyJe3YVYO8DX-pSUB/s72-c/pde_pte_4k.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8237815422107266951.post-4211505155125700460</id><published>2009-12-16T22:32:00.004+01:00</published><updated>2009-12-16T23:47:34.810+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="assembly"/><category scheme="http://www.blogger.com/atom/ns#" term="cpu"/><title type='text'>On moving register</title><content type='html'>One of the great *cough* things of the IA32 architecture is that it offers multiple ways to encode identical instructions. For instance, the &lt;span style=&quot;font-style: italic;&quot;&gt;mov&lt;/span&gt; instruction is implemented by several opcodes - to support &lt;a href=&quot;http://sandpile.org/ia32/opc_1.htm&quot;&gt;multiple variations&lt;/a&gt; of the instruction, for instance &lt;span style=&quot;font-style: italic;&quot;&gt;mov reg, [mem]&lt;/span&gt;, &lt;span style=&quot;font-style: italic;&quot;&gt;mov reg, imm&lt;/span&gt; , etc.).&lt;br /&gt;Specifically, opcode 89h (&lt;span style=&quot;font-style: italic;&quot;&gt;mov Ev, Gv&lt;/span&gt;) and opcode 8Bh (&lt;span style=&quot;font-style: italic;&quot;&gt;mov Gv, Ev&lt;/span&gt;) are used to encode &lt;span style=&quot;font-style: italic;&quot;&gt;mov [mem], reg&lt;/span&gt; and &lt;span style=&quot;font-style: italic;&quot;&gt;mov reg, [mem]&lt;/span&gt;, respectively. Both are also used to encode &lt;span style=&quot;font-style: italic;&quot;&gt;mov reg, reg&lt;/span&gt;. So which one should we use?&lt;br /&gt;&lt;br /&gt;With Microsoft dev tools (MASM, CL), opcode 8B was chosen. This means that &lt;span style=&quot;font-weight: bold; font-style: italic;&quot;&gt;mov ebp, esp&lt;/span&gt;, this classic compiler idiom used in function prologues, is implemented as &lt;span style=&quot;font-weight: bold;&quot;&gt;8B EC&lt;/span&gt;; the alternate form being &lt;span style=&quot;font-weight: bold;&quot;&gt;89 E5&lt;/span&gt; by the way.&lt;br /&gt;&lt;br /&gt;Yesterday, I was wondering, &quot;Why the heck did MS decide to implement move from register to register this way in their compiler suite? Did they have &lt;span style=&quot;font-style: italic;&quot;&gt;some&lt;/span&gt; Intel guidance here? Did they flip a coin? ...&quot;. Anyways, I could not believe this choice was innocent.&lt;br /&gt;&lt;br /&gt;I first had a quick look at &lt;a href=&quot;http://www.intel.com/Assets/PDF/manual/248966.pdf&quot;&gt;Intel&#39;s optimization manual&lt;/a&gt; but couldn&#39;t find a hint in it - I may have missed that though.&lt;br /&gt;&lt;br /&gt;So I decided to code a simple program to benchmark both instructions. I focused on &quot;mov ebp, esp&quot; since it&#39;s what initially this whole thing...&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;__declspec(naked) __int64 test1(void)&lt;br /&gt;{&lt;br /&gt;__asm&lt;br /&gt;{&lt;br /&gt;rdtsc&lt;br /&gt;push    edx&lt;br /&gt;push    eax&lt;br /&gt;&lt;br /&gt;mov     edx, ebp&lt;br /&gt;mov     eax, esp&lt;br /&gt;&lt;br /&gt;mov     ecx, COUNT&lt;br /&gt;dummy:&lt;br /&gt;_emit   0x8B    // mov ebp, esp&lt;br /&gt;_emit   0xEC&lt;br /&gt;add     esp, 0x1234&lt;br /&gt;dec     ecx&lt;br /&gt;jg      dummy&lt;br /&gt;&lt;br /&gt;mov     ebp, edx&lt;br /&gt;mov     esp, eax&lt;br /&gt;&lt;br /&gt;rdtsc&lt;br /&gt;sub     eax, [esp]&lt;br /&gt;sbb     edx, [esp+4]&lt;br /&gt;add     esp, 8&lt;br /&gt;&lt;br /&gt;retn&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style=&quot;font-style: italic;&quot;&gt;test1&lt;/span&gt;&#39;s counterpart, &lt;span style=&quot;font-style: italic;&quot;&gt;test2&lt;/span&gt;, is exactly the same routine except that the &lt;span style=&quot;font-style: italic;&quot;&gt;mov&lt;/span&gt; is implemented as 89 E5. I ran both of these 10 times with COUNT set to 100 millions. The output below shows the routine duration in CPU tick count for &lt;span style=&quot;font-style: italic;&quot;&gt;test1&lt;/span&gt; (t1), &lt;span style=&quot;font-style: italic;&quot;&gt;test2&lt;/span&gt; (t2), and the delta (t2-t1).&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;266427630, 239098970 -&gt; -27328660&lt;br /&gt;198251880, 236396490 -&gt; 38144610&lt;br /&gt;197485280, 236592800 -&gt; 39107520&lt;br /&gt;198359910, 240731530 -&gt; 42371620&lt;br /&gt;198169630, 236203160 -&gt; 38033530&lt;br /&gt;199283790, 237357990 -&gt; 38074200&lt;br /&gt;198334600, 238307940 -&gt; 39973340&lt;br /&gt;201726060, 237601250 -&gt; 35875190&lt;br /&gt;199196030, 235864980 -&gt; 36668950&lt;br /&gt;197668180, 236878930 -&gt; 39210750&lt;br /&gt;198189520, 236734830 -&gt; 38545310&lt;br /&gt;198769940, 236796360 -&gt; 38026420&lt;br /&gt;198463880, 236996720 -&gt; 38532840&lt;br /&gt;197608520, 235117620 -&gt; 37509100&lt;br /&gt;198994300, 237364120 -&gt; 38369820&lt;br /&gt;198324810, 238987550 -&gt; 40662740&lt;br /&gt;197842630, 236818990 -&gt; 38976360&lt;br /&gt;197126140, 236928430 -&gt; 39802290&lt;br /&gt;198637450, 237262350 -&gt; 38624900&lt;br /&gt;197569520, 235503910 -&gt; 37934390&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Omitting the first line (performance likely impacted by the CPU caching the memory area containing both routines), it appears that the first form is about 20% faster than the second. And this is not not stack-register specific as I had the same result with &lt;span style=&quot;font-style: italic;&quot;&gt;mov eax, edx&lt;/span&gt; for instance.&lt;br /&gt;&lt;br /&gt;So, using opcode 8B for &lt;span style=&quot;font-style: italic;&quot;&gt;mov reg, reg&lt;/span&gt; seems like a good choice - in practice, I have no clue if this makes a difference during execution of a real program.&lt;br /&gt;&lt;br /&gt;I still don&#39;t know why this choice is what it is though... if anyone (somebody who worked on a real-world C compiler for instance) has a clue, please leave a comment.&lt;br /&gt;&lt;br /&gt;Update: I&#39;ve just noticed NASM generates the alternate form 89 E5.&lt;br /&gt;&lt;br /&gt;As for the guesswork: an assembler, to decide which opcode could be used to implement the desired instruction, can use different approach. A simple one could be to go through the opcodes in sequence (00 though FF, then 0F 00 through 0F FF, etc.), and use the first opcode encountered that fits. In this case, that would be 89. And now that I&#39;m writing this, I realize that the simple x86 assembler I wrote in the past uses this method, and therefore should generate 89 E5 like NASM does. The fact that Microsoft tools do not makes me think it is a deliberate design decision...</content><link rel='replies' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/4211505155125700460/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/8237815422107266951/4211505155125700460' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/4211505155125700460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/4211505155125700460'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/2009/12/on-moving-register.html' title='On moving register'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8237815422107266951.post-8571880254081346780</id><published>2009-11-21T10:43:00.008+01:00</published><updated>2009-11-21T12:03:32.956+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cpu"/><title type='text'>Why are GDT descriptors so messed up?</title><content type='html'>Ever wondered why a GDT descriptor had such a fragmented format? Like anybody born in the 80&#39;s, I have.&lt;br /&gt;&lt;br /&gt;Here is a 64-bit, standard, non-system, generic GDT segment descriptor:&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9bEqZ4PnKTzhAPeJTdHh2sOqIAI3uN5c79pCzThxe2-9lvJPF_5PcT-P61VA78-oNVzFcgix98vU1rNjvtBROkbSm_RqHm-Hv6r2Zdt9rj40wDBSLsmUoHjTR3ONL6G0oC9kESVrcEG3i/s1600/gdt-descriptor.png&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 61px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9bEqZ4PnKTzhAPeJTdHh2sOqIAI3uN5c79pCzThxe2-9lvJPF_5PcT-P61VA78-oNVzFcgix98vU1rNjvtBROkbSm_RqHm-Hv6r2Zdt9rj40wDBSLsmUoHjTR3ONL6G0oC9kESVrcEG3i/s320/gdt-descriptor.png&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5406491765307714434&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;The base address is fragmented into 2 pieces (low 24 bits, high 8 bits), as is the segment limit (low 16 bits, high 8 bits). Why so?&lt;br /&gt;&lt;br /&gt;The answer is, you guessed, &lt;span style=&quot;font-style: italic;&quot;&gt;backward compatibility&lt;/span&gt;. And the guilty is the 80286. This processor was introduced in 1982, and was the first to support Protected Mode (PM). This PM was not exactly the one we know and use nowadays though; it was simpler, sort of a version 0.1 is you will.&lt;br /&gt;&lt;br /&gt;The &lt;a href=&quot;http://www.ragestorm.net/downloads/286intel.txt&quot;&gt;286 manual&lt;/a&gt; here shows us the encoding of a standard GDT descriptor - check figure 6-3. Its size is 8 bytes, but the upper 2 bytes &quot;must be set to 0 for compatibility with iAPX 386&quot;. Interesting; so even then, they were envisaging &lt;span style=&quot;font-style: italic;&quot;&gt;some&lt;/span&gt; PM extensions...  The meaningful data is contained in the low 6 bytes, formatting a non-fragmented descriptor:&lt;br /&gt;- bytes 0-1: 16-bit limit&lt;br /&gt;- bytes 2-4: 24-bit base&lt;br /&gt;- byte 5: flags&lt;br /&gt;&lt;br /&gt;So wait. Does it mean a segment can be at max 64Kb? And a 24-bit base means that only 16Mb of memory are physically addressable, right? - you say. Well, yes and yes. It&#39;s old-PM, remember.&lt;br /&gt;&lt;br /&gt;The new version introduced by the 386 has its lot of improvements, among which:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Real 32-bit addressing: an extra byte for the base (8th position) was added, making it 32-bit long&lt;/li&gt;&lt;li&gt;The possibility to have 4Gb long segments (as opposed to 64Kb...): 4 bits were added to the limit field, making it 20 bits. Since 20 bits can only address 1Mb, 4 extra attribute bits were added, including the G bit (pos.23). Setting the G(ranularity) bit means the limit field indicates the last addressable 4-Kb block. Therefore, one sets the limit to 0xFFFFF with G=1 to have a 4Gb segment (like all modern OS do).&lt;/li&gt;&lt;/ul&gt;Which explains why GDT descriptors seem so messed up...&lt;br /&gt;&lt;br /&gt;Another interesting bit introduced in the extra 4-bit of the attributes field is the D/B bit (pos.22). This bit indicates the default operand-size of the segment, and setting it to 1 means it&#39;s 32-bit. It was of course set to 0 for the 286 &quot;6-byte&quot; descriptors. Just one more element that just shows how the 386 was the real cornerstone, implementing the things that lacked in the 286 (including the paging unit), and became a standard.&lt;br /&gt;&lt;br /&gt;If you want to know more about this, check out the Wikipedia &lt;a href=&quot;http://en.wikipedia.org/wiki/Protected_mode#History&quot;&gt;PM history section&lt;/a&gt; as well as the 286 manual mentioned earlier. Also, a very interesting trivia on the 286 is how the inability to switch back from protected-mode to real-more gave &lt;a href=&quot;http://blogs.msdn.com/larryosterman/archive/2005/02/08/369243.aspx&quot;&gt;a few guys at Microsoft&lt;/a&gt; some very hard (and fun) time!</content><link rel='replies' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/8571880254081346780/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/8237815422107266951/8571880254081346780' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/8571880254081346780'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/8571880254081346780'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/2009/11/why-are-gdt-descriptors-so-messed-up.html' title='Why are GDT descriptors so messed up?'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9bEqZ4PnKTzhAPeJTdHh2sOqIAI3uN5c79pCzThxe2-9lvJPF_5PcT-P61VA78-oNVzFcgix98vU1rNjvtBROkbSm_RqHm-Hv6r2Zdt9rj40wDBSLsmUoHjTR3ONL6G0oC9kESVrcEG3i/s72-c/gdt-descriptor.png" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8237815422107266951.post-1346491046006464610</id><published>2009-11-06T16:14:00.005+01:00</published><updated>2009-11-06T16:51:42.514+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="assembly"/><category scheme="http://www.blogger.com/atom/ns#" term="hacks"/><title type='text'>Detecting simple hypervisors</title><content type='html'>This was tested only on Intel VT-x but it might work as well with AMD-V. In between a couple of blue screens, I realized there exist many simple ways to detect primitive HVM rootkits - ie, the ones that don&#39;t implement all the code required to achieve super-stealth.&lt;br /&gt;&lt;br /&gt;Let me give you a simple example. CPUID is a peculiar instruction; it&#39;s the only non ring-0 allowed instruction that will unconditionally trigger a VM-exit (Vol.3B:253669, p21-2). If you trace over CPUID in your favorite debugger, the VM-exit will happen: the CPU enters VMX-Root mode, and your VMM is called to handle the offending instruction.&lt;br /&gt;&lt;br /&gt;The lazy coder would write something like:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;// emulate CPUID&lt;br /&gt;if(Reason == EXIT_REASON_CPUID) then&lt;br /&gt;    pushad&lt;br /&gt;    mov     eax, GuestEax&lt;br /&gt;    mov     ecx, GuestEcx&lt;br /&gt;    cpuid&lt;br /&gt;    mov     GuestEax, eax&lt;br /&gt;    mov     GuestEcx, ecx&lt;br /&gt;    mov     GuestEdx, edx&lt;br /&gt;    mov     GuestEbx, ebx&lt;br /&gt;    popad&lt;br /&gt;    ...&lt;br /&gt;&lt;br /&gt;// update isntruction pointer&lt;br /&gt;GuestEip += 2&lt;br /&gt;&lt;br /&gt;vmresume()&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Well, that&#39;s not enough. Execution will resume after CPUID. The trap flag will raise the debug exception after executing the instruction that follows... and there you have one simple way to detect poorly coded HVMs. One way to prevent this would be to inject a vectored event (INT1) on VM-entry.&lt;br /&gt;&lt;br /&gt;This piece of assembly code implements the above trick  (if we may call it so):&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;    call    GetCurrentProcess&lt;br /&gt;    push    1&lt;br /&gt;    push    eax&lt;br /&gt;    call    SetProcessAffinityMask&lt;br /&gt;&lt;br /&gt;    push    offset seh&lt;br /&gt;    push    dword ptr fs:[0]&lt;br /&gt;    mov     fs:[0], esp&lt;br /&gt;&lt;br /&gt;    pushfd&lt;br /&gt;    or      dword ptr [esp], 100h&lt;br /&gt;    popfd&lt;br /&gt;&lt;br /&gt;    cpuid&lt;br /&gt;&lt;br /&gt;traphere:&lt;br /&gt;    mov     eax, 1&lt;br /&gt;    jmp     done&lt;br /&gt;    &lt;br /&gt;seh:&lt;br /&gt;    mov     eax, [esp+0Ch]&lt;br /&gt;    cmp     dword ptr [eax+0B8h], traphere&lt;br /&gt;    setne   al&lt;br /&gt;    movzx   eax, al&lt;br /&gt;&lt;br /&gt;done:&lt;br /&gt;    add     eax, 30h&lt;br /&gt;    push    eax&lt;br /&gt;    push    esp&lt;br /&gt;    call    crt_printf&lt;br /&gt;&lt;br /&gt;    push    eax&lt;br /&gt;    call    ExitProcess&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;(On SMP systems, change the thread affinity to execute the test on other CPUs.)&lt;br /&gt;&lt;br /&gt;There are other similar ways to detect a hypervisor from user-mode - again, assuming its implementation is lacking.</content><link rel='replies' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/1346491046006464610/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/8237815422107266951/1346491046006464610' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/1346491046006464610'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/1346491046006464610'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/2009/11/detecting-simple-hypervisors.html' title='Detecting simple hypervisors'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8237815422107266951.post-2824491591469649248</id><published>2009-07-16T11:07:00.009+02:00</published><updated>2009-07-17T11:06:53.559+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="malware"/><title type='text'>New Mebroot domains for the summer</title><content type='html'>The last variant of Mebroot&#39;s driver uses an obfuscated domain generation algorithm to connect to C&amp;C servers. Here are the domains for this summer, you might want to block them for whatever reason.&lt;br /&gt;&lt;br /&gt;The first domain, week-based, is used first (though, after the hardcoded domain in the driver itself); the second domain is day-based and used as a failsafe. On top of &#39;.com&#39;, the TLDs &#39;.net&#39; and &#39;.biz&#39; are tried as well.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;2009/07/17: bdcxduds.com xdjxekgt.com&lt;br /&gt;2009/07/18: bdcxduds.com ejswwhvk.com&lt;br /&gt;2009/07/19: swuvxcds.com khkciudw.com&lt;br /&gt;2009/07/20: swuvxcds.com kxhwcceu.com&lt;br /&gt;2009/07/21: swuvxcds.com xhxvdsck.com&lt;br /&gt;2009/07/22: swuvxcds.com hkssvihg.com&lt;br /&gt;2009/07/23: swuvxcds.com jwjchkci.com&lt;br /&gt;2009/07/24: swuvxcds.com vkcvuksd.com&lt;br /&gt;2009/07/25: swuvxcds.com ecjhdvue.com&lt;br /&gt;2009/07/26: vxvtvhik.com kvcwhwgj.com&lt;br /&gt;2009/07/27: vxvtvhik.com kvbdxjhc.com&lt;br /&gt;2009/07/28: vxvtvhik.com uuvksskh.com&lt;br /&gt;2009/07/29: vxvtvhik.com tkevtxue.com&lt;br /&gt;2009/07/30: vxvtvhik.com vdkhsccs.com&lt;br /&gt;2009/07/31: vxvtvhik.com feuufscg.com&lt;br /&gt;2009/08/01: vxvtvhik.com gcuekdss.com&lt;br /&gt;2009/08/02: wjbijxix.com ubhxghvt.com&lt;br /&gt;2009/08/03: wjbijxix.com vcdgcseb.com&lt;br /&gt;2009/08/04: wjbijxix.com ugfdvxck.com&lt;br /&gt;2009/08/05: wjbijxix.com wdbbgwej.com&lt;br /&gt;2009/08/06: wjbijxix.com fgugcijb.com&lt;br /&gt;2009/08/07: wjbijxix.com twsssthu.com&lt;br /&gt;2009/08/08: wjbijxix.com bfithbdd.com&lt;br /&gt;2009/08/09: ufcsbgsg.com cgkgttfg.com&lt;br /&gt;2009/08/10: ufcsbgsg.com fxxubvcg.com&lt;br /&gt;2009/08/11: ufcsbgsg.com egihvgjf.com&lt;br /&gt;2009/08/12: ufcsbgsg.com fkcxifec.com&lt;br /&gt;2009/08/13: ufcsbgsg.com ukxsuvhw.com&lt;br /&gt;2009/08/14: ufcsbgsg.com fxkihkfi.com&lt;br /&gt;&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/2824491591469649248/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/8237815422107266951/2824491591469649248' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/2824491591469649248'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/2824491591469649248'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/2009/07/new-mebroot-domains-for-summer.html' title='New Mebroot domains for the summer'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8237815422107266951.post-7249197879943743572</id><published>2009-03-09T11:19:00.007+01:00</published><updated>2011-10-08T21:08:50.929+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="math"/><title type='text'>ProjectEuler problem 144</title><content type='html'>&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;http://projecteuler.net/project/images/p_144_1.gif&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 268px; height: 240px;&quot; src=&quot;http://projecteuler.net/project/images/p_144_1.gif&quot; alt=&quot;&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://projecteuler.net/&quot;&gt;Project Euler&lt;/a&gt; is a website offering math challenges solvable by programming - usually  few tens lines of code are enough. Last friday, after more than a year of Euler abstinence, I decided to have a look at it again, and ran across this cool problem (#144, check it out &lt;a href=&quot;http://projecteuler.net/index.php?section=problems&amp;amp;id=144&quot;&gt;here&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;http://projecteuler.net/project/images/p_144_2.gif&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 141px; height: 287px;&quot; src=&quot;http://projecteuler.net/project/images/p_144_2.gif&quot; alt=&quot;&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So the goal is to find the number of times the laser beam will hit the ellipse-shaped cell before exiting through the input cavity.&lt;br /&gt;First, let&#39;s formulate the problem with simple trigonometry. Have a look at the schema below:&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8zOXY3XJsQ5cA4f9iYTYSHMVSBVFvOzaERmev9i0BIBwuLgePSe_N03Wwh-VFjHZ-kusJVBfHmVAatuLGc9yr7SlYkqlHfUqM89drT6TUlyPSFIQE46AdxnKMsJlLOYNrRMI9YFXbBWSe/s1600-h/144-info.jpg&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 165px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8zOXY3XJsQ5cA4f9iYTYSHMVSBVFvOzaERmev9i0BIBwuLgePSe_N03Wwh-VFjHZ-kusJVBfHmVAatuLGc9yr7SlYkqlHfUqM89drT6TUlyPSFIQE46AdxnKMsJlLOYNrRMI9YFXbBWSe/s320/144-info.jpg&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5311154734308927570&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The laser beam comes from A and hits the ellipse at point 0. We can calculate the slope m0: (yO-yA)/(xO-xA); we can also calculate the slope m1: -4*x/y. We need to calculate slope m2 and deduce B in order to iterate this process (find the next point of impact).&lt;br /&gt;&lt;br /&gt;It appears clear that:&lt;br /&gt;a = a0-a1&lt;br /&gt;and&lt;br /&gt;a = a1+PI-a2&lt;br /&gt;&lt;br /&gt;Therefore:&lt;br /&gt;tan(a) = tan(a0-a1)&lt;br /&gt;= (tan(a0)-tan(a1))/(1+tan(a0)*tan(a1))&lt;br /&gt;= (m0-m1)/(1+m0*m1)&lt;br /&gt;&lt;br /&gt;and&lt;br /&gt;tan(a) = tan(a1+PI-a2)&lt;br /&gt;= tan(a1-a2)&lt;br /&gt;= (tan(a1)-tan(a2))/(1+tan(a1)*tan(a2))&lt;br /&gt;= (m1-m2)/(1+m1*m2)&lt;br /&gt;&lt;br /&gt;Let&#39;s set X = (m0-m1)/(1+m0*m1)&lt;br /&gt;X = (m1-m2)/(1+m1*m2)&lt;br /&gt;-&amp;gt; m2 = (m1-X)/(1+X*m1)&lt;br /&gt;&lt;br /&gt;We have the slope m2 of the reflected beam (OB). With the coordinates of O (x0,y0), we have the equation of the line:&lt;br /&gt;y = a*x+b, with a=m2 and b=y0-m2*x0&lt;br /&gt;&lt;br /&gt;The last step is calculate the coordinates of B. We have:&lt;br /&gt;- the equation of the ellipse: 4*x^2+y^2 = 100&lt;br /&gt;- the equation of (0B): y = m2*x+b&lt;br /&gt;&lt;br /&gt;It boils down to solving the quadratic:&lt;br /&gt;x^2*(4+a^2) + x*(2*a*b) + (b^2-100) = 0&lt;br /&gt;&lt;br /&gt;And then we yield the coordinates of B. After a few &lt;span style=&quot;font-style: italic;&quot;&gt;300-and-something&lt;/span&gt; iterations (nah I wouldn&#39;t spoil your Euler fun) you&#39;ll find out the reflected point falls onto the exit hole. Problem solved!</content><link rel='replies' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/7249197879943743572/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/8237815422107266951/7249197879943743572' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/7249197879943743572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/7249197879943743572'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/2009/03/projecteuler-problem-144.html' title='ProjectEuler problem 144'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8zOXY3XJsQ5cA4f9iYTYSHMVSBVFvOzaERmev9i0BIBwuLgePSe_N03Wwh-VFjHZ-kusJVBfHmVAatuLGc9yr7SlYkqlHfUqM89drT6TUlyPSFIQE46AdxnKMsJlLOYNrRMI9YFXbBWSe/s72-c/144-info.jpg" height="72" width="72"/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8237815422107266951.post-4170011865871569836</id><published>2009-03-04T20:42:00.004+01:00</published><updated>2009-03-04T20:45:25.917+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="sudoku"/><title type='text'>Sudoku solver</title><content type='html'>Nothing new or original here.&lt;br /&gt;&lt;a href=&quot;http://code.google.com/p/miscellaneouz/source/browse/trunk/sudoku/sudoku.py&quot;&gt;This Sudoku solver&lt;/a&gt; just aims to show how compact Python code can be...&lt;br /&gt;The core of this piece of code is less than 40 lines of code. And we could do much better than that.</content><link rel='replies' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/4170011865871569836/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/8237815422107266951/4170011865871569836' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/4170011865871569836'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/4170011865871569836'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/2009/03/sudoku-solver.html' title='Sudoku solver'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8237815422107266951.post-4753179813658353596</id><published>2009-02-14T18:03:00.004+01:00</published><updated>2009-03-01T13:34:06.229+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="code"/><title type='text'>Real-time stock quotes Python API</title><content type='html'>I&#39;ve put up a handy script on my Google code area right &lt;a href=&quot;http://code.google.com/p/miscellaneouz/source/browse/trunk/pybourso/pybourso.py&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This Python module works like a very simple interface to get stock quotes from the French stock website &lt;span style=&quot;font-weight:bold;&quot;&gt;Boursorama&lt;/span&gt;. You can get securities of any trading place providing you know its ISIN of course.&lt;br /&gt;&lt;br /&gt;The cool stuff about it is that it gives you &lt;span style=&quot;font-weight:bold;&quot;&gt;real-time&lt;/span&gt; quotes (yes, you avoid the 15/20-min delay Yahoo and co. give you).&lt;br /&gt;&lt;br /&gt;Here&#39;s how to use it:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ from pybourso import get_stock&lt;br /&gt;$ e = get_stock(&#39;US38259P5089&#39;)&lt;br /&gt;$ print e[&#39;name&#39;], e[&#39;value&#39;], e[&#39;variation&#39;]&lt;br /&gt;&lt;br /&gt;GOOGLE INC, 357.66, -1.49&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Check out the source to see all that&#39;s returned by &lt;span style=&quot;font-weight:bold;&quot;&gt;get_stock()&lt;/span&gt;. Enjoy!</content><link rel='replies' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/4753179813658353596/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/8237815422107266951/4753179813658353596' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/4753179813658353596'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/4753179813658353596'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/2009/02/real-time-stock-quotes-python-api.html' title='Real-time stock quotes Python API'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8237815422107266951.post-8897928961444558873</id><published>2009-02-09T21:00:00.002+01:00</published><updated>2009-03-01T13:34:29.330+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="code"/><title type='text'>csheap</title><content type='html'>csheap is a customizable dynamic memory allocator written in C. It was originally written as a replacement for the standard libc malloc and the Windows runtime.&lt;br /&gt;&lt;br /&gt;I&#39;ve put it up on Google Code &lt;a href=&quot;http://code.google.com/p/csheap/&quot;&gt;here&lt;/a&gt;. Enjoy.</content><link rel='replies' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/8897928961444558873/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/8237815422107266951/8897928961444558873' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/8897928961444558873'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/8897928961444558873'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/2009/02/csheap.html' title='csheap'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8237815422107266951.post-504010609811403280</id><published>2009-01-08T17:51:00.002+01:00</published><updated>2009-01-08T17:56:34.452+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="assembly"/><title type='text'>pushfd and popfd are slow...</title><content type='html'>...damn, damn slow!&lt;br /&gt;Use lahf/sahf instead.&lt;br /&gt;A few numbers later on - if I have time.</content><link rel='replies' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/504010609811403280/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/8237815422107266951/504010609811403280' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/504010609811403280'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/504010609811403280'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/2009/01/pushfd-and-popfd-are-slow.html' title='pushfd and popfd are slow...'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8237815422107266951.post-6881647516957157883</id><published>2008-09-20T20:15:00.000+02:00</published><updated>2008-09-20T20:15:52.714+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="automation"/><category scheme="http://www.blogger.com/atom/ns#" term="poker"/><title type='text'>Why gambling on online Poker sites is a bad idea</title><content type='html'>On top of being forbidden by law in many countries, gambling online is not the smartest idea one may have.&lt;br /&gt;&lt;br /&gt;Poker is meant to be played in real life: you&#39;re supposed to see, even feel, your opponents. This process implies close surveillance: would you allow your real-life Poker friends to have their &#39;Poker maths&#39; and &#39;Poker stats for dummies&#39; at arm&#39;s reach. I&#39;d certainly not.&lt;br /&gt;&lt;br /&gt;When you&#39;re playing online, you may or may not be cheated in such ways. How would you? For instance, I know two people playing Hold&#39;em together online, exchanging their hands over IM and sharing their profit. OK, it&#39;s far from organized crime... but we could easily imagine programs analyzing the board, eventually exchanging information with other programs playing at the same table, and reaching a decision together in an automated fashion.&lt;br /&gt;&lt;br /&gt;Simpler, a bot could easily analyze the board, compute winning odds, and give the human player a decision hint.&lt;br /&gt;&lt;br /&gt;For fun (and NOT profit), I coded a proof-of-concept program. It&#39;s meant to analyze tables of a well- known online Texas Hold&#39;em program, compute and display odds. Inoffensive, but this would be the first and most important step of a &quot;poker bot&quot;.&lt;br /&gt;&lt;br /&gt;I prefer not to give names here... Anybody familiar with online poker will easily figure them out anyways. Here&#39;s the table (with many elements blurred out or removed):&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2ldQa_pBBbzktXQxnFHynABYaZe6_uHEITXM2yyDmK_mK88GnMW1x0diAOo-uUWfuUj5b552QPaGv_El-uWF9UIuaryua64qh4_1z-1hyJ8eC4g0Pyeot2CfKOTHUis4vWrFMtCCYLTQR/s1600-h/poker_table.jpg&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2ldQa_pBBbzktXQxnFHynABYaZe6_uHEITXM2yyDmK_mK88GnMW1x0diAOo-uUWfuUj5b552QPaGv_El-uWF9UIuaryua64qh4_1z-1hyJ8eC4g0Pyeot2CfKOTHUis4vWrFMtCCYLTQR/s320/poker_table.jpg&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5248121396581028834&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The analyzer program output is:&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhL6Emw4NtrZr30PWoiIuvu93SouPzELk9HOidhKjBMtyv_1fJ0sajJ-JZuh9hQ6CLKN3HyszmAcB9u_WYYhtj7qSYcvyG4IJO7F2XlgIGrSwQ3CimFmYsRQDd1BdzYYj1X-V2m5zgaUOVM/s1600-h/poker_analysis.jpg&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhL6Emw4NtrZr30PWoiIuvu93SouPzELk9HOidhKjBMtyv_1fJ0sajJ-JZuh9hQ6CLKN3HyszmAcB9u_WYYhtj7qSYcvyG4IJO7F2XlgIGrSwQ3CimFmYsRQDd1BdzYYj1X-V2m5zgaUOVM/s320/poker_analysis.jpg&quot; border=&quot;0&quot; alt=&quot;&quot;id=&quot;BLOGGER_PHOTO_ID_5248121768683756066&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here, I&#39;m triggering an analysis manually. Primitive OCR routines read table information, such as player positions, who&#39;s got the button, private cards, common cards, etc. Then, a separate component simulates thousands of games based on the information fed by the OCR component, and finally displays more or less useful statistics.&lt;br /&gt;&lt;br /&gt;In our example, we have As,6h, the stage is (River;9s,Ad,4s,Tc,Jc) and we&#39;re competing against 3 other players. The estimated odds are 24.6% (for an average 25% since we&#39;re 4 players). This ratio may be used as a hint by a human player, or, if the program is extended (pot and players&#39; stacks analysis, etc.), could be used as a building block for a fully automated poker-playing program...&lt;br /&gt;&lt;br /&gt;This is a basic PoC code, nothing exceptionnal here. We could easily imagine that bad guys have poker bots in place; now, how would you feel being the sucker competing against 9 bots exchanging cards... play money&#39;s fine, real money&#39;s a different story.</content><link rel='replies' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/6881647516957157883/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/8237815422107266951/6881647516957157883' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/6881647516957157883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/6881647516957157883'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/2008/09/why-gambling-on-online-poker-sites-is.html' title='Why gambling on online Poker sites is a bad idea'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2ldQa_pBBbzktXQxnFHynABYaZe6_uHEITXM2yyDmK_mK88GnMW1x0diAOo-uUWfuUj5b552QPaGv_El-uWF9UIuaryua64qh4_1z-1hyJ8eC4g0Pyeot2CfKOTHUis4vWrFMtCCYLTQR/s72-c/poker_table.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8237815422107266951.post-4021849558171571550</id><published>2008-09-17T12:13:00.009+02:00</published><updated>2009-02-14T13:05:52.920+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="hacks"/><title type='text'>Getting free Velib&#39; w/o getting tired</title><content type='html'>A cool thing about Paris is its public bicycle system, called &lt;a href=&quot;http://velib.paris.fr&quot;&gt;Velib&#39;&lt;/a&gt;. The concept is fairly simple: for 30 euro a year, you can take and use any bicycle available around the ~1000 stations spread across the city.&lt;br /&gt;&lt;br /&gt;The rules: You may take your Velib&#39; at point A and give it back at point B. You may use it up to 30 minutes for free; if you use it more than that, you will pay (1 euro for the next half-hour slice, and so on).&lt;br /&gt;&lt;br /&gt;The downside of the system is that a few stations, mainly these located at higher altitudes, were usually empty, whereas stations close to them, but at lower altitudes, were packed very quickly (for obvious reasons).&lt;br /&gt;&lt;br /&gt;This problem was solved a few months back, when about 10% of the stations (*mainly*, the highest-located ones) were converted to V+ stations. The concept is simple: When you borrow a bicycle in a regular station and bring it back to a V+ one, you get extra credit. This virtual money can then be used to pay your extra time when you borrow a Velib&#39; for more than 30 minutes.&lt;br /&gt;&lt;br /&gt;Now, you see where I&#39;m going! Some V+ stations are really close to regular stations, as you can see on this &lt;a href=&quot;http://www.velib.paris.fr/trouver_une_station&quot;&gt;page&lt;/a&gt;. But how close exactly? And which ones are the best spots, ie, V+ super close to a V stations? Filling up an account with extra credit might not be that exhausting after all...&lt;br /&gt;&lt;br /&gt;The GMap map used on the above page is fed with Velib&#39; stations data from the following &lt;a href=&quot;http://www.velib.paris.fr/service/carto&quot;&gt;XML feed&lt;/a&gt;. It contains the station names, addresses, geo-coordinates, as well as flags (is the station in operation? is it a bonus station?).&lt;br /&gt;&lt;br /&gt;If we calculate primitive euclidean distances between 2 stations using their (longitude; lattitude) coordinates, omitting the altitude, we could easily figure out, for each of the 90 operating V+ stations, which regular station is the closest...&lt;br /&gt;&lt;br /&gt;Now, I&#39;ll spare you the code (very easy to write, check it out &lt;a href=&quot;http://code.google.com/p/miscellaneouz/source/browse/trunk/velib/bestvelib.py&quot;&gt;here&lt;/a&gt;), and will go straight to the best results. The format is (V+, V, distance):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;09018 - PLACE PIGALLE &amp;gt; 09019 - VICTOR MASSE (0.000919)&lt;br /&gt;09004 - ROCHECHOUART GERANDO &amp;gt; 09006 - TRUDAINRE ROCHECHOUART (0.000945)&lt;br /&gt;18043 - BLANCHE &amp;gt; 09027 - FONTAINE DOUAI (0.001091)&lt;br /&gt;14030 - LOSSERAND - PERNETY &amp;gt; 14104 - LOSSERAND BOYER-BARRET (0.001106)&lt;br /&gt;18041 - MARTYRS 2 &amp;gt; 09017 - TRUDAINE MARTYRS (0.001140)&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Let&#39;s visually check our best couple on the map, which are stations 09018 and 09019:&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDJEHhZt1MTtB-Gd65-l36fnJO1A0G9EhSIlMpxLn57c2MDRH6paLDBw3fUopvqPidLA61z6anPoOippfBzDSEK4-PNACnRLMepVyuMwJWrLcbdQo_oqcyCVQp2IOUQDL2KpmLE-E7nbZy/s1600-h/velib_09018_09019.jpg&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDJEHhZt1MTtB-Gd65-l36fnJO1A0G9EhSIlMpxLn57c2MDRH6paLDBw3fUopvqPidLA61z6anPoOippfBzDSEK4-PNACnRLMepVyuMwJWrLcbdQo_oqcyCVQp2IOUQDL2KpmLE-E7nbZy/s320/velib_09018_09019.jpg&quot; border=&quot;0&quot; alt=&quot;&quot;id=&quot;BLOGGER_PHOTO_ID_5247001732097955922&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Yep, seems OK to me. One might go to Pigalle for *different* reasons after all...</content><link rel='replies' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/4021849558171571550/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/8237815422107266951/4021849558171571550' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/4021849558171571550'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/4021849558171571550'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/2008/09/getting-free-velib-wo-getting-tired.html' title='Getting free Velib&#39; w/o getting tired'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDJEHhZt1MTtB-Gd65-l36fnJO1A0G9EhSIlMpxLn57c2MDRH6paLDBw3fUopvqPidLA61z6anPoOippfBzDSEK4-PNACnRLMepVyuMwJWrLcbdQo_oqcyCVQp2IOUQDL2KpmLE-E7nbZy/s72-c/velib_09018_09019.jpg" height="72" width="72"/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8237815422107266951.post-5211712762399597133</id><published>2008-09-14T16:17:00.000+02:00</published><updated>2008-09-14T16:18:04.614+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="compression"/><title type='text'>Rar(e) juicy bits</title><content type='html'>I recently spent time working on the Rar algorithm. Though the compression routines are not disclosed, Eugene Roshal freely provides the &lt;a href=&quot;http://www.rarlab.com/rar/unrarsrc-3.8.2.tar.gz&quot;&gt;sources&lt;/a&gt; for the command line version of its decompressor. It’s the only real pieces of information available out there – the other documents you may find concern the archive file format itself.&lt;br /&gt;&lt;br /&gt;A few context elements first: Several versions of the Rar program exist, along with different major versions of the algorithm behind it. The one we&#39;re interested in is version 2.9, the algorithm in use in Rar version 3. Version  2.9 compresses blocks of data using either a Lempel/Ziv or a PPM (Prediction by Partial Matching) algorithm.&lt;br /&gt;&lt;br /&gt;The interesting thing is that special symbols can be found in the compressed data stream to notify the presence of VM bytecode. Yes, you read right: v29 makes use of a virtual machine. The VM code is interpreted after decompression, and is used for unfiltering the data.&lt;br /&gt;&lt;br /&gt;To achieve better compression ratios, data is usually filtered/modified by a compressor program - ie, a filter&#39;s goal is to decrease the entropy of the data to be compressed. A very common example is when compressing x86 binary files: relative jumps and calls (0xE8, 0xE9) can be replaced by their fake, absolute equivalents. A jmp $+5 (E8 00 00 00 00 ) at offset 0x100 would be replaced by E8 05 01 00 00. This filter is used by various executable packers (ex: AsProtect), as well as compressors (ex: SevenZip, Rar) or installers (ex: InnoSetup).&lt;br /&gt;&lt;br /&gt;Version 2.9 makes use of several filters, for images, videos, audio files, binary files, etc. However, in this very case, the unfiltering routine is encoded in the compressed stream itself, with the use of the VM bytecode. That’s where v29 potentially allows more flexibility than other compressor programs.&lt;br /&gt;&lt;br /&gt;Available VM opcodes are the following (check out vmrar.hpp):&lt;br /&gt;VM_MOV, VM_CMP, VM_ADD, VM_SUB, VM_JZ, VM_JNZ, VM_INC, VM_DEC, VM_JMP, VM_XOR, VM_AND, VM_OR, VM_TEST, VM_JS, VM_JNS, VM_JB, VM_JBE, VM_JA, VM_JAE, VM_PUSH, VM_POP, VM_CALL, VM_RET, VM_NOT, VM_SHL, VM_SHR, VM_SAR, VM_NEG, VM_PUSHA,VM_POPA, VM_PUSHF,VM_POPF, VM_MOVZX,VM_MOVSX,VM_XCHG, VM_MUL, VM_DIV, VM_ADC, VM_SBB, VM_PRINT, VM_MOVB, VM_MOVD, VM_CMPB, VM_CMPD, VM_ADDB, VM_ADDD, VM_SUBB, VM_SUBD, VM_INCB, VM_INCD, VM_DECB, VM_DECD, VM_NEGB, VM_NEGD, VM_STANDARD&lt;br /&gt;&lt;br /&gt;Looks very similar to x86 opcodes, isn&#39;t it? If you go through this whole list, you may wonder what VM_STANDARD stands for? Well, without this opcode, reversing standard filters would be incredibly slooooow! VM_STANDARD instructs the VM that a standard filter is used, and that a hard-coded decoding routine can be executed to speed the process.&lt;br /&gt;&lt;br /&gt;VM_STANDARD is not found in the bytecode stream per se, but is generated by the program when the bytecode stream exhibits characteristics such as particular length and crc:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;VM_StandardFilters RarVM::IsStandardFilter(byte *Code,int CodeSize)&lt;br /&gt;{&lt;br /&gt;struct StandardFilterSignature&lt;br /&gt;{&lt;br /&gt;  int Length;&lt;br /&gt;  uint CRC;&lt;br /&gt;  VM_StandardFilters Type;&lt;br /&gt;} StdList[]={&lt;br /&gt;  53, 0xad576887, VMSF_E8,&lt;br /&gt;  57, 0x3cd7e57e, VMSF_E8E9,&lt;br /&gt; 120, 0x3769893f, VMSF_ITANIUM,&lt;br /&gt;  29, 0x0e06077d, VMSF_DELTA,&lt;br /&gt; 149, 0x1c2c5dc8, VMSF_RGB,&lt;br /&gt; 216, 0xbc85e701, VMSF_AUDIO,&lt;br /&gt;  40, 0x46b9c560, VMSF_UPCASE&lt;br /&gt;};&lt;br /&gt;uint CodeCRC=CRC(0xffffffff,Code,CodeSize)...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here’s an example: The stream is being decompressed; the current symbol is 0x101, which instructs the decompressor that VM bytecode is to be read (check out unpack.cpp). The bytecode is processed; it contains VM initialization values, as well as a VM opcode sequence. Now, when the filter is to be applied, the opcodes could be processed one by one. Emulating hundreds of VM_MOV, VM_CMP and others is a computationally expensive task. Therefore, what the decompressor does first is to check the opcode sequence length and CRC against a list of known VM routines. These routines are for commonly used filters. If one of these standard routines is matched, then a VM_STANDARD opcode is generated, its operand being the VMSF_Xxx constant referring to the hardcoded routine executed instead of bytecode emulation.&lt;br /&gt;&lt;br /&gt;So far, 6 standard filters routines are available:&lt;br /&gt;- x86 jumps and/or call filters (VMSF_E8, VMSF_E8E9)&lt;br /&gt;- Intel Itanium filter (VMSF_ITANIUM)&lt;br /&gt;- RGB filter (VMSF_RGB)&lt;br /&gt;- Audio files filters (VMSF_AUDIO)&lt;br /&gt;- Image filters (VMSF_DELTA)&lt;br /&gt;- Case filters (VMSF_UPCASE)&lt;br /&gt;&lt;br /&gt;This choice of having a VM to run the filters offers extension possibilities yet to be seen, maybe via the use of plugins in later versions of Rar? One could then create a special filter, designed to achieve very good compression ratios with particular files. Not to mention that the filters can be organized in a filter stack, reused, and applied one after each other, etc. Quite powerful.&lt;br /&gt;&lt;br /&gt;Last thing: how do you decide which filters are applied to your compressed data? Well, you quite don’t. The compressor will decide for you (let me remind you that they’re all closed source). Hmm... going back to Unrar source code, it appears cmddata.cpp contains the code responsible for handling command line parameters of Unrar. In fact, cmddata.cpp contains command line options for Rar and Unrar (it’s very likely that the sources are a subset of Rar+Unrar sources, and the compilation of a specific program is decided via a pre-processor #define).&lt;br /&gt;&lt;br /&gt;You may notice that the switch –mc allows the user to force-enable/disable the use of a particular filter:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;case &#39;M&#39;:&lt;br /&gt;  switch(etoupper(Switch[1]))&lt;br /&gt;  {&lt;br /&gt;  case &#39;C&#39;:&lt;br /&gt;    // ...cut...&lt;br /&gt;    switch(etoupper(*(Str++)))&lt;br /&gt;    {&lt;br /&gt;      case &#39;T&#39;: Type=FILTER_PPM; break;&lt;br /&gt;      case &#39;E&#39;: Type=FILTER_E8; break;&lt;br /&gt;      case &#39;D&#39;: Type=FILTER_DELTA; break;&lt;br /&gt;      ...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;PPM is a compression mode; it has the role of a dummy filter here. Let’s fire Rar command-line now, to see if these options are advertised:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ rar -h&lt;br /&gt;Usage:  rar command -switch1 -switchN archive files ...&lt;br /&gt;(cut)&lt;br /&gt;mcX    Set advanced compression parameters&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;What does &quot;advanced compression parameters&quot; mean? It seems RarLab is not quite ready to let their users decide what filters they would like to use, let alone code their own filters via the use of the VM.&lt;br /&gt;&lt;br /&gt;If you want to know more, well, check out the &lt;a href=&quot;http://www.rarlab.com/rar/unrarsrc-3.8.2.tar.gz&quot;&gt;Unrar source code&lt;/a&gt;, more specifically unpack.cpp/hpp, rarvm.cpp/hpp and cmddata.cpp.</content><link rel='replies' type='application/atom+xml' href='http://0x5a4d.blogspot.com/feeds/5211712762399597133/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/8237815422107266951/5211712762399597133' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/5211712762399597133'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8237815422107266951/posts/default/5211712762399597133'/><link rel='alternate' type='text/html' href='http://0x5a4d.blogspot.com/2008/09/rare-juicy-bits.html' title='Rar(e) juicy bits'/><author><name>Nico</name><uri>http://www.blogger.com/profile/05080355975786609839</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>