<?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: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-4121626987179262004</id><updated>2011-12-01T20:07:50.987+08:00</updated><category term='virtualization'/><category term='look&apos;n&apos;stop'/><category term='wireshark'/><category term='plugin'/><category term='debugging'/><category term='software'/><category term='google chrome'/><category term='security'/><title type='text'>Flier's Sky</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://flierlu.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://flierlu.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Flier Lu</name><uri>http://www.blogger.com/profile/01953688425888938834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4121626987179262004.post-7094853607383018087</id><published>2008-12-31T00:35:00.005+08:00</published><updated>2008-12-31T10:17:24.810+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='google chrome'/><title type='text'>Change the default zoom mode in Google Chromium</title><content type='html'>&lt;p&gt;As a &lt;a href="http://webkit.org/"&gt;WebKit&lt;/a&gt; based browser, Google Chrome use the text zoom mode as default zoom mode. It means, if you choose the Zoom -&gt; Larger in the page context menu, or press the Ctrl + '+' accelerator, all the text font size in the page will be increased by 20%. On the other hand, if you do the same thing in FireFox, the whole page will be zoomed instead the text font size. &lt;/p&gt;&lt;p&gt;In my opinion, I feel the page zoom mode more comfortable, although I don't think any of those mode is better than the other. At least in my 24' LCD with 1080p, I need the page zoom width enough to fill the right space. &lt;/p&gt;&lt;p&gt;So, I just modified Chrome source code, add two alternative accelerators for page zoom mode; I also add a command line switch to set the default zoom mode when starting.&lt;/p&gt;&lt;p&gt;The changes are straight, because WebKit had provided the build-in support for page zoom mode, and Chrome also had an internal switch for zoom mode. &lt;/p&gt;&lt;p&gt;Following steps are the changes base on latest SVN revision.&lt;br /&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Add two new command definition in the \app\chrome_dll_resource.h file, which define the alternative zoom command itself.&lt;br /&gt;&lt;br /&gt;#define IDC_ZOOM_VIEW_PLUS 38004&lt;br /&gt;#define IDC_ZOOM_VIEW_MINUS 38005&lt;br /&gt;&lt;br /&gt;And add new accelerator like Ctrl + Alt + '+'/'-' in the IDR_MAINFRAME table (app\chrom_dll.rc)&lt;br /&gt;&lt;br /&gt;VK_ADD,              IDC_ZOOM_VIEW_PLUS, VIRTKEY, CONTROL, ALT&lt;br /&gt;VK_SUBTRACT,         IDC_ZOOM_VIEW_MINUS, VIRTKEY, CONTROL, ALT&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Handle the commands in the Browser::ExecuteCommand function (\browser\browser.cc), and add a parameter for ZoomIn/ZoomOut functions which is the zoom mode&lt;br /&gt;&lt;br /&gt;// Zoom&lt;br /&gt;case IDC_ZOOM_PLUS: ZoomIn(true); break;&lt;br /&gt;case IDC_ZOOM_NORMAL: ZoomReset(); break;&lt;br /&gt;case IDC_ZOOM_MINUS: ZoomOut(true); break;&lt;br /&gt;case IDC_ZOOM_VIEW_PLUS: ZoomIn(false); break;&lt;br /&gt;case IDC_ZOOM_VIEW_MINUS: ZoomOut(false); break;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Add two new zoom mode in PageZoom (\common\page_zoom.h), which will be used for page zoom; and refactor ZoomIn/ZoomOut functions (\browser\browser.cc) for new modes.&lt;br /&gt;&lt;br /&gt;enum Function {&lt;br /&gt;VIEW_SMALLER = -2,&lt;br /&gt;SMALLER = -1,&lt;br /&gt;STANDARD = 0,&lt;br /&gt;LARGER = 1,&lt;br /&gt;VIEW_LARGER = 2, };&lt;br /&gt;&lt;br /&gt;void Browser::ZoomIn(bool isTextOnly) {&lt;br /&gt;UserMetrics::RecordAction(L"ZoomPlus", profile_);&lt;br /&gt;GetSelectedTabContents()-&gt;AsWebContents()-&gt;render_view_host()-&gt;Zoom( isTextOnly ? PageZoom::LARGER : PageZoom::VIEW_LARGER);}&lt;br /&gt;&lt;br /&gt;void Browser::ZoomOut(bool isTextOnly) {&lt;br /&gt;UserMetrics::RecordAction(L"ZoomMinus", profile_);&lt;br /&gt;GetSelectedTabContents()-&gt;AsWebContents()-&gt;render_view_host()-&gt;Zoom( isTextOnly ? PageZoom::SMALLER : PageZoom::VIEW_SMALLER);}&lt;br /&gt;&lt;br /&gt;Then, the RenderViewHost::Zoom function will wrap the zoom mode as a ViewMsg_Zoom message, and send it to the render process.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Modify the render handler, which redirect ViewMsg_Zoom message to OnZoom function (\renderer\render_view.cc)&lt;br /&gt;&lt;br /&gt;IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom)&lt;br /&gt;&lt;br /&gt;The OnZoom function has a hard code kZoomIsTextOnly constant. So, we just change its value base on the command line parameter; and set two kind of zoom mode base on its default setting.&lt;br /&gt;&lt;br /&gt;void RenderView::OnZoom(int function) {&lt;br /&gt;static const bool zoomIsTextOnly = CommandLine().HasSwitch(switches::kZoomIsTextOnly);&lt;br /&gt;&lt;br /&gt;switch (function) {&lt;br /&gt;case PageZoom::VIEW_SMALLER:&lt;br /&gt;webview()-&gt;ZoomOut(!zoomIsTextOnly); break;&lt;br /&gt;case PageZoom::SMALLER: webview()-&gt;ZoomOut(zoomIsTextOnly); break;&lt;br /&gt;case PageZoom::STANDARD: webview()-&gt;ResetZoom(); break;&lt;br /&gt;case PageZoom::LARGER: webview()-&gt;ZoomIn(zoomIsTextOnly); break;&lt;br /&gt;case PageZoom::VIEW_LARGER: webview()-&gt;ZoomIn(!zoomIsTextOnly); break;&lt;br /&gt;default: NOTREACHED(); }}&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Besides the command workflow, there are some bookkeeping works.&lt;br /&gt;&lt;br /&gt;We need update the command status base on the current stage in the Browser::UpdateCommandsForTabState function (browser\browser.cc)&lt;br /&gt;&lt;br /&gt;controller_.UpdateCommandEnabled(IDC_ZOOM_VIEW_PLUS, is_web_contents);&lt;br /&gt;controller_.UpdateCommandEnabled(IDC_ZOOM_VIEW_MINUS, is_web_contents);&lt;br /&gt;&lt;/li&gt;&lt;li&gt;To change the default zoom mode, I added a new switch for command line in \common\chrome_switches.h/.cc&lt;br /&gt;&lt;br /&gt;// Turns on text only mode zoom supportconst wchar_t&lt;br /&gt;kZoomIsTextOnly[] = L"zoom-is-text-only";&lt;br /&gt;&lt;br /&gt;and add it into the switch_names array in RenderProcessHost::Init function (browser\render_process_host.cc). So, the browser process will propagate the switch to the child render process.&lt;br /&gt;&lt;br /&gt;static const wchar_t* const switch_names[] = {&lt;br /&gt;//...&lt;br /&gt;switches::kZoomIsTextOnly, };&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Besides, I found a &lt;a href="http://code.google.com/p/chromium/issues/detail?id=404&amp;amp;q=zoom&amp;amp;colspec=ID%20Stars%20Pri%20Area%20Type%20Status%20Summary%20Modified%20Owner"&gt;similar feature request&lt;/a&gt; has been submited to the chrome issues tracking. So, I will add some comment as patch for this issue. Wish Google could merge it into next offical release :)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4121626987179262004-7094853607383018087?l=flierlu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flierlu.blogspot.com/feeds/7094853607383018087/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4121626987179262004&amp;postID=7094853607383018087' title='41 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/7094853607383018087'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/7094853607383018087'/><link rel='alternate' type='text/html' href='http://flierlu.blogspot.com/2008/12/change-default-zoom-mode-in-google.html' title='Change the default zoom mode in Google Chromium'/><author><name>Flier Lu</name><uri>http://www.blogger.com/profile/01953688425888938834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>41</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4121626987179262004.post-2684899923462351246</id><published>2008-10-15T18:26:00.005+08:00</published><updated>2008-10-15T19:10:10.653+08:00</updated><title type='text'>Use 3rd party font render engine in Google Chromium</title><content type='html'>&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; &lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;   As you know, there are some 3rd party font engines, such as &lt;/span&gt;&lt;a href="http://www39.atwiki.jp/gdiplusplus/"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;GDI++&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;, which could hook Windows font related APIs, and render font more smoother. &lt;br /&gt;    In my opinion, that engine seems better than &lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/ClearType"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;ClearType&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt; or other build-in Windows font engine. &lt;/span&gt;&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;    For Chromium, it use &lt;/span&gt;&lt;a href="http://dev.chromium.org/developers/design-documents/multi-process-architecture"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;multi-processes architecture&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;, a standalone renderer process will render the page in sandbox. It means that we should know which process need be hooked for font smoother. &lt;/span&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://dev.chromium.org/_/rsrc/1220197832277/developers/design-documents/multi-process-architecture/arch.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px;" src="http://dev.chromium.org/_/rsrc/1220197832277/developers/design-documents/multi-process-architecture/arch.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style=" ;font-family:arial;"&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;    So I made some slight changes in Chromium to support GDI++ &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;    &lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;1. a new command line parameter "--use-gdipp=&lt;/span&gt;&lt;/span&gt;&lt;filename&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;", which give a setting file for GDI++ &lt;/span&gt;&lt;/span&gt;&lt;/filename&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;    I add a new key name kUseGdiPP (chrome_switches.h|.cc), which could be used to parse command line parameters.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;const wchar_t kUseGdiPP[] = L"use-gdipp";&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;    And also add it in switch_names array (render_process_host.cc), that control the main browser process propagate which switches to renderer child process.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;    &lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;2. the initi&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;alize and finalize code in RendererMain function, which load and free the font engine &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;    After the renderer process started, it call RendererMain function (renderer_main.cc) to initilize process. So I add the font engine related code just after HandleRendererErrorTestParameters calling. Because that function could help us debugging the children process.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  bool use_gdipp = parsed_command_line.HasSwitch(switches::kUseGdiPP);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  if (use_gdipp)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    std::wstring setting_file_name = &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      parsed_command_line.GetSwitchValue(switches::kUseGdiPP);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    if (!LoadFontEngine(setting_file_name.c_str()))&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      LOG(WARNING) &lt;&lt; "Fail to load GDI++ font engine.";&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      use_gdipp = false;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    else&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;      DLOG(INFO) &lt;&lt; "Loaded GDI++ font engine.";&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;    We can use "--renderer-startup-dialog" parameter to popup a message box before any other initialize code. And we could attach debugger to renderer process for troubeshooting. Besides, this parameter must be used with "--no-sandbox" parameter. Please check &lt;/span&gt;&lt;a href="http://dev.chromium.org/developers/how-tos/debugging"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;Debugging Chromium&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt; for more detail.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;     On the other hand, we also free the font engine before uninitialize COM with CoUninitialize function.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  if (use_gdipp)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;    FreeFontEngine();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;  &lt;span class="Apple-style-span" style="font-weight: bold;"&gt; &lt;span class="Apple-style-span" style="font-size: medium;"&gt; 3. a customized GDI++ library which will be linked as static library in chrome.dll library &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;    To compile the GDI++ library, you should download the latest &lt;/span&gt;&lt;a href="http://www39.atwiki.jp/gdiplusplus/pages/12.html"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;FreeType version GDI++&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;, with &lt;/span&gt;&lt;a href="http://www.freetype.org/"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;FreeType&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt; and &lt;/span&gt;&lt;a href="http://research.microsoft.com/sn/detours/"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;Detours&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;    And create a static library project in chrome solution, which should add all the source files in GDI++\src folder except run.cpp.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;    Than, you should do some dirty works to make it compilable, remove some function definition and includes.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;    Two funtions LoadFontEngine and FreeFontEngine should be added in hook.cpp as wrapper, and a new header file should be created to declare those functions.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;bool LoadFontEngine(LPCTSTR lpszFile)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  hook_initinternal();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  CCriticalSectionLock::Init();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  if (!g_TLInfo.ProcessInit()) &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;    return false;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  CGdippSettings* pSettings = CGdippSettings::CreateInstance();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  if (!pSettings || !pSettings-&gt;LoadAppSettings(lpszFile)) &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;    CGdippSettings::DestroyInstance();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;    return false;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  if (!FontLInit()) &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;    return false;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  g_pFTEngine = new FreeTypeFontEngine;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  if (!g_pFTEngine) &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;    return false;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  if (!InterlockedExchange(&amp;amp;g_bHookEnabled, TRUE))&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;    hook_init();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  }  &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  return true;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;void FreeFontEngine()&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  if (InterlockedExchange(&amp;amp;g_bHookEnabled, FALSE)) &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;    hook_term();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  if (g_pFTEngine) delete g_pFTEngine;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  FontLFree();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  CGdippSettings::DestroyInstance();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  g_TLInfo.ProcessTerm();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;  CCriticalSectionLock::Term();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style=" ;font-family:georgia;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;After that, you could get a local build with GDI++, it depend on freetype6.dll, zlib1.dll and detoured.dll as cost. And you could customize your setting file for GDI++, and run your local chrome with it. For more detail, you could read its offical document (Japanese), guess it by name or google it. :)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style=" ;font-family:arial;font-size:32px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4121626987179262004-2684899923462351246?l=flierlu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flierlu.blogspot.com/feeds/2684899923462351246/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4121626987179262004&amp;postID=2684899923462351246' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/2684899923462351246'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/2684899923462351246'/><link rel='alternate' type='text/html' href='http://flierlu.blogspot.com/2008/10/use-3rd-party-font-render-engine-in.html' title='Use 3rd party font render engine in Google Chromium'/><author><name>Flier Lu</name><uri>http://www.blogger.com/profile/01953688425888938834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4121626987179262004.post-720380861903858716</id><published>2008-04-02T22:39:00.005+08:00</published><updated>2008-04-02T23:09:42.201+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='virtualization'/><title type='text'>Virtualization Detection</title><content type='html'>&lt;div&gt;&lt;br /&gt;&lt;div&gt;As you know, virtualization is changing traditional IT infrastructure.&lt;br /&gt;VMware &lt;a href="http://www.vmware.com/products/vi/esx/"&gt;ESX server&lt;/a&gt;, the market leading hypervisor, has been accepted by &lt;a href="http://www.vmware.com/a/customers/"&gt;customers of all sizes&lt;/a&gt;, including all of the Fortune 100; Microsoft Windows 2008 also integrate &lt;a href="http://www.microsoft.com/windowsserver2008/en/us/hyperv-faq.aspx"&gt;Hyper-V&lt;/a&gt; as a core server role; several open source projects also focus on it, such as &lt;a href="http://www.citrixxenserver.com/products/Pages/myproducts.aspx"&gt;Xen&lt;/a&gt; (Intel), &lt;a href="http://kvm.qumranet.com/kvmwiki"&gt;KVM&lt;/a&gt; (Linux) and &lt;a href="http://www.virtualbox.org/"&gt;Virtual Box&lt;/a&gt; (Sun) etc.&lt;br /&gt;&lt;br /&gt;There are a lot of research papers and online discussion about Virtualization Detection&lt;br /&gt;&lt;br /&gt;The 1st option is using vender specific public interface or backdoor, which could provide rich information about host OS and virtualization.&lt;br /&gt;&lt;br /&gt;Microsoft public a &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=91E2E518-C62C-4FF2-8E50-3A37EA4100F5&amp;amp;displaylang=en"&gt;Hypervisor Functional Specification&lt;/a&gt; for its Hyper-V implementation, which includes definition about not only feature and interface discovery but also Hyper-Call based management interfaces.&lt;br /&gt;We could directly use one simple CPUID instruction to detect the existent of Hyper-V.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;bool CHyperV::Exists(void)&lt;br /&gt;{&lt;br /&gt;int cpuid[4];&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;__cpuid(cpuid, 1);&lt;br /&gt;&lt;br /&gt;return cpuid[2] &amp;amp; (1 &lt;&lt;&gt;Further more, vender ID, neutral interface name, version and supported features could be fetched through similar method.&lt;br /&gt;&lt;br /&gt;VMware also has similar private interface through a magic I/O port, which includes not only implementation information but also runtime information, such as processor speed, mouse cursor position and clipboard etc.&lt;br /&gt;We could use its magic I/O port to detect the existent of VMware.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;bool CVMware::Exists(void)&lt;br /&gt;{&lt;br /&gt;bool exists = true;&lt;br /&gt;&lt;br /&gt;__try&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;__asm&lt;br /&gt;{&lt;br /&gt;push edx&lt;br /&gt;push ecx&lt;br /&gt;push ebx&lt;br /&gt;&lt;br /&gt;mov eax, 'VMXh'&lt;br /&gt;mov ebx, 0 // any value but not the MAGIC VALUE&lt;br /&gt;mov ecx, 10 // get VMWare version&lt;br /&gt;&lt;br /&gt;mov edx, 'VX' // port number&lt;br /&gt;&lt;br /&gt;in eax, dx // read port&lt;br /&gt;&lt;br /&gt;// on return EAX returns the VERSION&lt;br /&gt;cmp ebx, 'VMXh' // is it a reply from VMWare?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;setz [exists] // set return value&lt;br /&gt;&lt;br /&gt;pop ebx&lt;br /&gt;pop ecx&lt;br /&gt;pop edx&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;__except(EXCEPTION_EXECUTE_HANDLER)&lt;br /&gt;{&lt;br /&gt;exists = false;&lt;br /&gt;}&lt;br /&gt;return exists;&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;For more completely commands list, you could check the following URL&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;VMware Backdoor I/O Port&lt;br /&gt;&lt;a href="http://chitchat.at.infoseek.co.jp/vmware/backdoor.html"&gt;http://chitchat.at.infoseek.co.jp/vmware/backdoor.html&lt;/a&gt;&lt;/blockquote&gt;VMware also provide an open source project, &lt;a href="http://open-vm-tools.sourceforge.net/"&gt;Open Virtual Machine Tools&lt;/a&gt;, which includes more detail usage of its backdoor.&lt;br /&gt;&lt;br /&gt;Besides, Microsoft Virtual PC/Server, bochs, qemu has similar interface, you could check the following URLs for more detail.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;How to detect Virtual PC or VMware from your program&lt;br /&gt;&lt;a href="http://www.codegurus.be/codegurus/Programming/virtualpc&amp;amp;vmware_en.htm"&gt;http://www.codegurus.be/codegurus/Programming/virtualpc&amp;amp;vmware_en.htm&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Attacks on Virtual Machine Emulators&lt;br /&gt;&lt;a href="http://www.symantec.com/avcenter/reference/Virtual_Machine_Threats.pdf"&gt;http://www.symantec.com/avcenter/reference/Virtual_Machine_Threats.pdf&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;The 2nd option is checking VM implementation mechanism, which could detect some unknown VM vender in theory.&lt;br /&gt;&lt;br /&gt;The mostly famous method is checking IDT register from Joanna’s Red Pill.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Red Pill... or how to detect VMM using (almost) one CPU instruction&lt;br /&gt;&lt;a href="http://invisiblethings.org/papers/redpill.html"&gt;http://invisiblethings.org/papers/redpill.html&lt;/a&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#999999;"&gt;The heart of this code is actually the SIDT instruction (encoded&lt;br /&gt;as 0F010D[addr]), which stores the contents of the interrupt descriptor table register (IDTR) in the destination operand, which is actually a memory location. What is special and interesting about SIDT instruction is that, it can be executed in non privileged mode (ring3) but it returns the contents of the sensitive register, used internally by operating system.&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;&lt;span style="color:#999999;"&gt;Because there is only one IDTR register, but there are at least two OS running concurrently (i.e. the host and the guest OS), VMM needs to relocate the guest's IDTR in a safe place, so that it will not conflict with a host's one. Unfortunately, VMM cannot know if (and when) the process running in guest OS executes SIDT instruction, since it is not privileged (and it doesn't generate exception). Thus the process gets the relocated address of IDT table. It was observed that on VMWare, the relocated address of IDT is at address 0xffXXXXXX, whereas on Virtual PC it is 0xe8XXXXXX. This was tested on VMWare Workstation 4 and Virtual PC 2004, both running on Windows XP host OS.&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;/em&gt;&lt;/blockquote&gt;This method only use one SIDT instruction to detect the existent of VM, because a lot of x86 software VM implementation choose to change IDT for guest OS.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;bool CUnknown::CheckIDT(void)&lt;br /&gt;{&lt;br /&gt;unsigned char idt[6];&lt;br /&gt;&lt;br /&gt;_asm&lt;br /&gt;{&lt;br /&gt;sidt idt&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;return idt[5] &gt; 0xd0;&lt;br /&gt;}&lt;/blockquote&gt;Unfortunately, this method could be spoofed by VM implementation&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;SubVirt: Implementing malware with virtual machines&lt;br /&gt;&lt;a href="http://www.eecs.umich.edu/~pmchen/papers/king06.pdf"&gt;http://www.eecs.umich.edu/~pmchen/papers/king06.pdf&lt;/a&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#999999;"&gt;The redpill [39] virtual-machine detection technique detects the&lt;br /&gt;presence of a VMM by using the sidt instruction. The sidt instruction reads the address of the processor’s interrupt descriptor table. This address is different for an operating system running directly above hardware than for an operating system running above a VMM. VMMs emulate the sidt instruction when it is called from kernel-mode, but for performance reasons this instruction is not virtualized when called from user-mode. Thus, user-mode code can execute the&lt;br /&gt;sidt instruction to detect the presence of a VMM. To defeat this detection technique, we use virtual-machine introspection to emulate the sidt instruction when it is called by the redpill application.&lt;br /&gt;&lt;/span&gt;&lt;/em&gt;&lt;/blockquote&gt;&lt;br /&gt;And it also doesn’t work on some hardware accelerated VM implementation and multi-core CPU system.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Introducing Blue Pill&lt;br /&gt;&lt;a href="http://theinvisiblethings.blogspot.com/2006/06/introducing-blue-pill.html"&gt;http://theinvisiblethings.blogspot.com/2006/06/introducing-blue-pill.html&lt;/a&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#999999;"&gt;SubVirt was implemented on x86 hardware, which doesn't allow to achieve 100% virtualization, because there are number of sensitive instructions, which are not privileged, like the famous SIDT/SGDT/SLDT. This allows for trivial detection of the virtual mode - see e.g. my little Red Pill program. This however, doesn't apply to Blue Pill, as it relies on AMD SVM&lt;br /&gt;technology.&lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Detecting the Presence of Virtual Machines&lt;br /&gt;Using the Local Data Table&lt;br /&gt;&lt;a href="http://www.offensivecomputing.net/files/active/0/vm.pdf"&gt;http://www.offensivecomputing.net/files/active/0/vm.pdf&lt;/a&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#999999;"&gt;The SIDT mechanism as implemented by Tobias Klein [1] and&lt;br /&gt;separately by Joanna Rutkowska [2] is a method for detecting the presence of a virtual machine environment. While the test is by no means thorough, it is an effective test for the presence of an emulated CPU environment on a single-processor machine. There are various problems with the implementation, however. If a multi-core CPU is used, the interrupt descriptor table can change significantly when the process is run on different cores. Furthermore if two or more physical processors are present the same implementation issues apply.&lt;/span&gt;&lt;/em&gt;&lt;/blockquote&gt;To improve the issues of SIDT mechanism, a lot of attempts focus on similar register, such as GDT, LDT or TS register.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Detecting the Presence of Virtual Machines Using the Local Data Table&lt;br /&gt;&lt;a href="http://www.offensivecomputing.net/files/active/0/vm.pdf"&gt;http://www.offensivecomputing.net/files/active/0/vm.pdf&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Methods for Virtual Machine Detection&lt;br /&gt;&lt;a href="http://www.s21sec.com/descargas/vmware-eng.pdf"&gt;http://www.s21sec.com/descargas/vmware-eng.pdf&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;bool CUnknown::CheckGDT(void)&lt;br /&gt;{&lt;br /&gt;unsigned char gdt[6];&lt;br /&gt;_asm&lt;br /&gt;{&lt;br /&gt;sgdt gdt&lt;br /&gt;}&lt;br /&gt;return gdt[5] &gt; 0xd0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;bool CUnknown::CheckLDT(void)&lt;br /&gt;{&lt;br /&gt;unsigned char ldt[2];&lt;br /&gt;_asm&lt;br /&gt;{&lt;br /&gt;sldt ldt&lt;br /&gt;}&lt;br /&gt;return ldt[0] != 0 &amp;amp;&amp;amp; ldt[1] != 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;bool CUnknown::CheckTR(void)&lt;br /&gt;{&lt;br /&gt;unsigned char tr[2];&lt;br /&gt;&lt;br /&gt;_asm&lt;br /&gt;{&lt;br /&gt;str tr&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;return tr[0] == 0 &amp;amp;&amp;amp; tr[1] == 0x40;&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;The major problem of these kinds of detection methods is the researcher hard to test compatibility on every VM vender.&lt;br /&gt;&lt;br /&gt;After I made a simple test, it seems we hard to trust any of them, but we could made a hyper detection method base on more test results.&lt;br /&gt;&lt;a href="http://bp2.blogger.com/_SVVTcCKGvvk/R_OhWMzttkI/AAAAAAAAAR0/kyt6zGas5sA/s1600-h/table.PNG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5184664998800897602" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; CURSOR: hand" alt="" src="http://bp2.blogger.com/_SVVTcCKGvvk/R_OhWMzttkI/AAAAAAAAAR0/kyt6zGas5sA/s400/table.PNG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/flier.lu/FlierSSky/photo?authkey=VAaBdFSONHM#5184662572144375314"&gt;&lt;/a&gt;&lt;div&gt;&lt;br /&gt;&lt;br /&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt;The 3rd option is using VM specific defect, which mostly tight coupling with VM version.&lt;br /&gt;&lt;br /&gt;For example, eEye researcher published a detection method base on wrong far execution transfers behaviors.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;blockquote&gt;Another VMware Detection&lt;br /&gt;&lt;a href="http://eeyeresearch.typepad.com/blog/2006/09/another_vmware_.html"&gt;http://eeyeresearch.typepad.com/blog/2006/09/another_vmware_.html&lt;/a&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;div&gt;So, the real world is not perfect, we hard to use one hammer to solve all the problems. We should carefully define our purpose and scope of virtualization detection, and choose a hyper detection solution for major focus market.&lt;/div&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4121626987179262004-720380861903858716?l=flierlu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flierlu.blogspot.com/feeds/720380861903858716/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4121626987179262004&amp;postID=720380861903858716' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/720380861903858716'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/720380861903858716'/><link rel='alternate' type='text/html' href='http://flierlu.blogspot.com/2008/04/virtualization-detection.html' title='Virtualization Detection'/><author><name>Flier Lu</name><uri>http://www.blogger.com/profile/01953688425888938834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_SVVTcCKGvvk/R_OhWMzttkI/AAAAAAAAAR0/kyt6zGas5sA/s72-c/table.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4121626987179262004.post-1769452824246814984</id><published>2007-08-07T18:54:00.000+08:00</published><updated>2007-08-07T19:00:03.112+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='virtualization'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>New challenge for malware detection: Virtualization Based rootkit</title><content type='html'>&lt;span class="Normal"&gt;&lt;br /&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 12pt;"&gt;&lt;i style=""&gt;&lt;span lang="EN-US"&gt;Several days ago, &lt;a href="http://www.invisiblethingslab.com/"&gt;Invisible Things Lab&lt;/a&gt; release a new  open source project which named &lt;a href="http://www.bluepillproject.org/"&gt;Blue  Pill&lt;/a&gt;, the first battle ready hardware virtualization based rootkits. Even  the code is not sophisticated in this version; I also believe its impact is  profound significance. It is a starting gun for new trend of rootkits and  malware, which will promote the battle field from OS in-house to VM  level.&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 12pt;"&gt;&lt;i style=""&gt;&lt;span lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 12pt;"&gt;&lt;span lang="EN-US"&gt;Just two years ago, virtualization can only be implemented by  software emulation, base on &lt;a href="http://en.wikipedia.org/wiki/Interpreter_%28computing%29"&gt;interpreter&lt;/a&gt;,  &lt;a href="http://en.wikipedia.org/wiki/Binary_translation"&gt;binary translation&lt;/a&gt;  etc. We got some software solution, includes &lt;a href="http://www.vmware.com/products/ws/"&gt;VMware Workstation&lt;/a&gt;, Microsoft &lt;a href="http://www.microsoft.com/windows/products/winfamily/virtualpc/default.mspx"&gt;Virtual  PC&lt;/a&gt; and &lt;a href="http://www.virtualbox.org/"&gt;Virtual Box&lt;/a&gt; etc. But they  are hard to ensure enough performance and compatibility.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 12pt;"&gt;&lt;span lang="EN-US"&gt;But as the dual core and x64 become common, hardware virtualization  solution become the mainstream, includes &lt;a href="http://www.xensource.com/"&gt;Xen&lt;/a&gt;, &lt;a href="http://www.vmware.com/products/vi/esx/"&gt;VMware ESX Server&lt;/a&gt;, &lt;a href="http://www.microsoft.com/windowsserver/longhorn/default.mspx"&gt;Microsoft  Longhorn&lt;/a&gt; etc. These solutions base on CPU level support includes &lt;st1:city st="on"&gt;Intel&lt;/st1:city&gt; &lt;a href="http://www.intel.com/technology/virtualization/index.htm"&gt;VT&lt;/a&gt; and AMD  &lt;a href="http://www.amd.com/us-en/Processors/ProductInformation/0,,30_118_8826_14287,00.html"&gt;Pacifica  (AMD-V)&lt;/a&gt;, which introduce a new isolated level beside x86’s ring 0-3.  &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 12pt;"&gt;&lt;span lang="EN-US"&gt;A mini OS kernel will run in hypervisor mode (VMM), which manage  multi guest OS in normal mode (VM). VMM can monitor the status of VM, and take  over some operation in VM, such as IO, privileged instruction etc.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 12pt;"&gt;&lt;span lang="EN-US"&gt;This is the common workflow as the designer expected.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 36pt;"&gt;&lt;span lang="EN-US"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 12pt;"&gt;&lt;span lang="EN-US"&gt;But on the other hand, the world is not perfect. Some malicious guys  also can use those features to bypass traditional security solutions.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 12pt;"&gt;&lt;span lang="EN-US"&gt;First, some white hat guys from &lt;a href="http://www.umich.edu/"&gt;University of Michigan&lt;/a&gt; and &lt;a href="http://research.microsoft.com/"&gt;MSR&lt;/a&gt; release a paper &lt;a href="http://research.microsoft.com/%7Elorch/papers/subvirt.pdf"&gt;SubVirt:  implementing malware with virtual machines&lt;/a&gt; in 2006. They discuss the  possibility for a new type of malware, named virtual-machine based rootkit  (VMBR), which installs a virtual-machine monitor underneath an existing  operating system and hoists the original operating system into a virtual  machine.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 12pt;"&gt;&lt;span lang="EN-US"&gt;Second, &lt;a href="http://theinvisiblethings.blogspot.com/"&gt;Joanna  Rutkowska&lt;/a&gt; presented at the Black Hat Briefings 2006, for hers hardware  virtualization based rootkits, named &lt;a href="http://www.bluepillproject.org/"&gt;Blue Pill&lt;/a&gt;. This implementation base  on CPU support, don’t need any binary translation, and very hard to detect from  VM in-house.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 12pt;"&gt;&lt;span lang="EN-US"&gt;Besides, Dino Dai Zovi from &lt;a href="http://www.matasano.com/log/mtso"&gt;matasano&lt;/a&gt; also presented at Black Hat  USA 2006 about &lt;a href="http://www.blackhat.com/presentations/bh-usa-06/BH-US-06-Zovi.pdf"&gt;hardware  virtualization rootkits&lt;/a&gt;, with their implementation base on &lt;a href="http://www.xensource.com/products/xen/"&gt;Xen 3.0&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 36pt;"&gt;&lt;span lang="EN-US"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 12pt;"&gt;&lt;span lang="EN-US"&gt;With my experience, a new concept from idea to malware need one or  two year. Now, one year has gone, source is available, and the hardware support  will be more and more popular. Everything for this new type of malware is almost  ready, only two actors are still missing, a hardware virtualization based  rootkit from real world, and detection and clean security solution.&lt;/span&gt;&lt;/p&gt; &lt;p&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4121626987179262004-1769452824246814984?l=flierlu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flierlu.blogspot.com/feeds/1769452824246814984/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4121626987179262004&amp;postID=1769452824246814984' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/1769452824246814984'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/1769452824246814984'/><link rel='alternate' type='text/html' href='http://flierlu.blogspot.com/2007/08/new-challenge-for-malware-detection.html' title='New challenge for malware detection: Virtualization Based rootkit'/><author><name>Flier Lu</name><uri>http://www.blogger.com/profile/01953688425888938834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4121626987179262004.post-3782794659539026958</id><published>2007-07-10T21:46:00.000+08:00</published><updated>2007-07-11T00:04:14.210+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='look&apos;n&apos;stop'/><category scheme='http://www.blogger.com/atom/ns#' term='plugin'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='wireshark'/><title type='text'>Wireshark Dissector Plugin for Look'n'Stop</title><content type='html'>From a developer viewpoint, &lt;a href="http://www.looknstop.com/"&gt;Look'n'Stop&lt;/a&gt; is a great personal firewall. Even their design may not very clearly for the normal user, but if you have enough background knowledge, it can be a powerful analyzer for the security threats.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;After a packet be allowed or blocked by rule, Look'n'Stop record it to log and provide a dialog for detail information. But these information not enough for me, so I decide to write a plugin to got more :)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://bp1.blogger.com/_SVVTcCKGvvk/RpOeMaM_x8I/AAAAAAAAAOM/uaE_zBrr98U/s1600-h/dissector.buildin.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5085582340260874178" style="CURSOR: hand" alt="" src="http://bp1.blogger.com/_SVVTcCKGvvk/RpOeMaM_x8I/AAAAAAAAAOM/uaE_zBrr98U/s400/dissector.buildin.png" border="0" /&gt;&lt;/a&gt; &lt;/div&gt;&lt;div&gt;&lt;br /&gt;Fortunately, they provide some &lt;a href="http://www.looknstop.com/En/plugin_loggedevent_dev.htm"&gt;plugin API&lt;/a&gt; for log display and rule editor. Through those interfaces, I can pop up my dissector dialog to display the protocol tree of packet. &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;To avoid reinvent the wheel, I choose &lt;a href="http://www.wireshark.org/"&gt;Wireshark &lt;/a&gt;as background dissector. Because Wireshark, or more well know name - ethereal, is the best open source network protocol analyzer, and is the standard in many industries.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Even Wireshark has encapsulate all dissector in a &lt;a href="http://www.wireshark.org/docs/wsdg_html_chunked/ChapterDissection.html"&gt;library&lt;/a&gt;, its interface not clearly and stable, so I decide use its terminal-based edition - &lt;a href="http://www.wireshark.org/docs/wsug_html_chunked/AppToolstshark.html"&gt;tshark&lt;/a&gt;, as the major dissector, because it can read packet from stdin, and dump the protocol tree to stdou as XML format.&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;So the major data and control flow includes:&lt;/div&gt;&lt;ol&gt;&lt;li&gt;Look'n'Stop pass the packet data to our plugin through its API&lt;/li&gt;&lt;li&gt;plugin fork a tshark process for dissect&lt;/li&gt;&lt;li&gt;plugin dump the packet as libpcap format to tshark's stdin&lt;/li&gt;&lt;li&gt;tshark dissect the packet to protocol tree and output the XML to stdout&lt;/li&gt;&lt;li&gt;plugin fetch the XML output and parse it with &lt;a href="http://expat.sourceforge.net/"&gt;expat&lt;/a&gt;&lt;/li&gt;&lt;li&gt;plugin popup a tree-based dialog and render the protocol tree&lt;/li&gt;&lt;li&gt;popup dialog provide more feature, for example, save the packet as libpcap format&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Combine those steps, we got a new dissector plugin :) &lt;/p&gt;&lt;div&gt;&lt;a href="http://bp2.blogger.com/_SVVTcCKGvvk/RpOk0qM_yBI/AAAAAAAAAPM/zI32Qt4YuCk/s1600-h/dissector.tree.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5085589628820375570" style="CURSOR: hand" alt="" src="http://bp2.blogger.com/_SVVTcCKGvvk/RpOk0qM_yBI/AAAAAAAAAPM/zI32Qt4YuCk/s400/dissector.tree.png" border="0" /&gt;&lt;/a&gt; &lt;/div&gt;&lt;div&gt;You can select a field in protocol tree, and the corresponding data bytes will be highlight in the bottom editor. If you want to save the packet for more analyzer, just right-click the windows title, and choose "Save As" in system menu. it support save packet as libpcap, xml and text format. &lt;/div&gt;&lt;div&gt;&lt;br /&gt; &lt;/div&gt;&lt;div&gt;But before this, you should download and install wireshark first, and configure the installation path in plugin, such as&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://bp0.blogger.com/_SVVTcCKGvvk/RpOh8KM_x_I/AAAAAAAAAO4/MgWGLlifS-0/s1600-h/option.wireshark.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5085586459134511090" style="CURSOR: hand" alt="" src="http://bp0.blogger.com/_SVVTcCKGvvk/RpOh8KM_x_I/AAAAAAAAAO4/MgWGLlifS-0/s400/option.wireshark.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;If you input a valid path, plugin will fetch the version and copyright from tshark, and save it to registry to reuse in future. &lt;/div&gt;&lt;div&gt;&lt;br /&gt; &lt;/div&gt;&lt;div&gt;For the china user, I integrate some location information of IP address. You should download the latest IP database from &lt;a href="http://www.cz88.net/fox/"&gt;cz88.net&lt;/a&gt;, and configure the QQWry setting page, such as&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://bp0.blogger.com/_SVVTcCKGvvk/RpOi9KM_yAI/AAAAAAAAAPA/OOp4MIjwBFw/s1600-h/option.qqwry.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5085587575826008066" style="CURSOR: hand" alt="" src="http://bp0.blogger.com/_SVVTcCKGvvk/RpOi9KM_yAI/AAAAAAAAAPA/OOp4MIjwBFw/s400/option.qqwry.png" border="0" /&gt;&lt;/a&gt; &lt;/div&gt;&lt;div&gt;After you choose "Use QQWry ...", a location information will be appended after some IP field in protocol tree. &lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;If you have interest about this, please &lt;a href="http://flier.lu.googlepages.com/build-0.1.rar"&gt;download &lt;/a&gt;the prebuild binary or compire it by youself.&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;That's all, if you have any advices or want to improve it by yourself, please &lt;a href="mailto:flier.lu@gmail.com"&gt;contact me &lt;/a&gt;directly :)&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4121626987179262004-3782794659539026958?l=flierlu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flierlu.blogspot.com/feeds/3782794659539026958/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4121626987179262004&amp;postID=3782794659539026958' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/3782794659539026958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/3782794659539026958'/><link rel='alternate' type='text/html' href='http://flierlu.blogspot.com/2007/07/wireshark-dissector-plugin-for.html' title='Wireshark Dissector Plugin for Look&apos;n&apos;Stop'/><author><name>Flier Lu</name><uri>http://www.blogger.com/profile/01953688425888938834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_SVVTcCKGvvk/RpOeMaM_x8I/AAAAAAAAAOM/uaE_zBrr98U/s72-c/dissector.buildin.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4121626987179262004.post-5047969000568949319</id><published>2007-05-28T00:14:00.000+08:00</published><updated>2007-05-28T01:00:38.029+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='debugging'/><title type='text'>Write a debugger in 5 minutes with PyDbgEng</title><content type='html'>&lt;blockquote&gt;&lt;/blockquote&gt;    The debug mechanism of PyDbgEng is same to other Win32 debugger,  just create or attach to a debuggee process and call WaitForEvent to process the debug events, such as create process, load module etc.&lt;br /&gt;&lt;pre&gt;&lt;blockquote style="font-style: italic;"&gt;#!/usr/bin/env python&lt;br /&gt;import sys&lt;br /&gt;from PyDbgEng import *&lt;br /&gt;&lt;br /&gt;c = DebugClient()&lt;br /&gt;&lt;br /&gt;c.CreateProcess("ftp.exe", createFlags=[CreateFlags.ATTACH_ONLY_THIS_PROCESS,&lt;br /&gt;  CreateFlags.NEW_CONSOLE])&lt;br /&gt;&lt;br /&gt;while c.Control.WaitForEvent():&lt;br /&gt;pass&lt;/blockquote&gt;&lt;/pre&gt;The previous code is a simple debugger&lt;br /&gt;&lt;ol&gt;&lt;li&gt;create a debug session with DebugClient()&lt;/li&gt;&lt;li&gt;create the debuggee process with CreateProcess&lt;/li&gt;&lt;li&gt;attach to the new process with CreateFlags.ATTACH_ONLY_THIS_PROCESS&lt;/li&gt;&lt;li&gt;create a new console window for debuggee with CreateFlags.NEW_CONSOLE&lt;/li&gt;&lt;/ol&gt;To get more debug events, we must add some debug event callback&lt;br /&gt;&lt;pre&gt;&lt;blockquote style="font-style: italic;"&gt;def onCreateProcess(args):&lt;br /&gt;print "CreateProc: %08x-%08x %s\t%s" % (&lt;br /&gt;args.BaseOffset, args.BaseOffset+args.ModuleSize,&lt;br /&gt;args.ModuleName, args.ImageName)&lt;br /&gt;&lt;br /&gt;def onExitProcess(args):&lt;br /&gt;print "ExitProcess %d" % args.ExitCode&lt;br /&gt;&lt;br /&gt;def onCreateThread(args):&lt;br /&gt;print "CreateThread %x %08x %08x" % (args.Handle, args.DataOffset, args.StartOffset)&lt;br /&gt;&lt;br /&gt;def onExitThread(args):&lt;br /&gt;print "ExitThread %d" % args.ExitCode&lt;br /&gt;&lt;br /&gt;def onLoadModule(args):&lt;br /&gt;print "ModLoad: %08x-%08x %s\t%s" % (&lt;br /&gt;args.BaseOffset, args.BaseOffset+args.ModuleSize,&lt;br /&gt;args.ModuleName, args.ImageName)&lt;br /&gt;&lt;br /&gt;c.EventCallbacks.CreateProcess = onCreateProcess&lt;br /&gt;c.EventCallbacks.ExitProcess = onExitProcess&lt;br /&gt;c.EventCallbacks.CreateThread = onCreateThread&lt;br /&gt;c.EventCallbacks.ExitThread = onExitThread&lt;br /&gt;c.EventCallbacks.LoadModule = onLoadModule&lt;br /&gt;c.EventCallbacks.Attach()&lt;br /&gt;&lt;br /&gt;c.CreateProcess(...)&lt;/blockquote&gt;&lt;/pre&gt;Now, we will receive 5 kinds of debug events, which allow use show detail information, or do some action, such as add breakpoint, etc. After setting the callback and attach them to debugger, we can got events, like:&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;CreateProc: 01000000-01012000 ftp       ftp.exe&lt;br /&gt;ModLoad: 7c930000-7ca00000 ntdll        ntdll.dll&lt;br /&gt;ExitProcess 0&lt;/blockquote&gt;Other kinds of events are about the status or state changing for debug session, debuggee and symbol, we also can use callback to process them&lt;br /&gt;&lt;pre&gt;&lt;blockquote style="font-style: italic;"&gt;def onSessionStatus(args):&lt;br /&gt;print "SessionStatus: %s" % (str(args.Status))&lt;br /&gt;&lt;br /&gt;def onChangeEngineState(args):&lt;br /&gt;sys.stdout.write("EngineState: %s " % str(args.State))&lt;br /&gt;&lt;br /&gt;if EngineState.EXECUTION_STATUS == args.State:&lt;br /&gt; print ExecutionStatus.values[args.Argument &amp; 0xf]&lt;br /&gt;else:&lt;br /&gt; print "%x" % args.Argument&lt;br /&gt;&lt;br /&gt;c.EventCallbacks.SessionStatus = onSessionStatus&lt;br /&gt;c.EventCallbacks.ChangeEngineState = onChangeEngineState&lt;/blockquote&gt;&lt;/pre&gt;These events will allow you watch the order of state changing, like&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;EngineState: SYSTEMS 0&lt;br /&gt;EngineState: EXECUTION_STATUS NO_CHANGE&lt;br /&gt;EngineState: EXTENSIONS 0&lt;br /&gt;SessionStatus: ACTIVE&lt;br /&gt;EngineState: EXECUTION_STATUS BREAK&lt;br /&gt;EngineState: CURRENT_THREAD 0&lt;br /&gt;CreateProc: 01000000-01012000 ftp       ftp.exe&lt;br /&gt;EngineState: EXECUTION_STATUS BREAK&lt;br /&gt;EngineState: EXECUTION_STATUS BREAK&lt;br /&gt;EngineState: CURRENT_THREAD 0&lt;br /&gt;ModLoad: 7c930000-7ca00000 ntdll        ntdll.dll&lt;br /&gt;EngineState: EXECUTION_STATUS BREAK&lt;br /&gt;EngineState: EXECUTION_STATUS BREAK&lt;br /&gt;EngineState: CURRENT_THREAD 0&lt;/blockquote&gt;To act as a complete debugger, we add and process breakpoint for some predefined function&lt;br /&gt;&lt;pre&gt;&lt;blockquote style="font-style: italic;"&gt;def onLoadModule(args):&lt;br /&gt;print "ModLoad: %08x-%08x %s\t%s" % (&lt;br /&gt;  args.BaseOffset, args.BaseOffset+args.ModuleSize,&lt;br /&gt;  args.ModuleName, args.ImageName)&lt;br /&gt;&lt;br /&gt;if "WS2_32" == args.ModuleName:&lt;br /&gt;  bp = c.Control.AddBreakpoint(flags=[BreakpointFlag.ENABLED],&lt;br /&gt;      offset=c.Symbols.GetOffsetByName("WS2_32!socket")) &lt;br /&gt;&lt;br /&gt;  symbol = c.Symbols.GetNameByOffset(bp.Offset)&lt;br /&gt;  print "Add Breakpoint: %s %d @ %08x %s:%d" % (str(bp.Type[0]), bp.Id, bp.Offset, symbol[0], symbol[1])&lt;br /&gt;&lt;br /&gt;def onBreakpoint(args):&lt;br /&gt;bp = args.Breakpoint&lt;br /&gt;&lt;br /&gt;symbol = c.Symbols.GetNameByOffset(bp.Offset)&lt;br /&gt;print "Hit Breakpoint: %s %d @ %08x %s:%d" % (str(bp.Type[0]), bp.Id, bp.Offset, symbol[0], symbol[1])&lt;br /&gt;&lt;br /&gt;return ExecutionStatus.BREAK&lt;br /&gt;&lt;br /&gt;c.EventCallbacks.Breakpoint = onBreakpoint&lt;br /&gt;&lt;/blockquote&gt;&lt;/pre&gt;After the WS2_32 module was loaded, we use DebugControl.AddBreakpoint method to create a new code break for WS2_32!socket, which will be called after ftp.exe started. So we add onBreakpoint callback function to show which breakpoint was hit.&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;ModLoad: 71b60000-71b77000 WS2_32      C:\WINDOWS\system32\WS2_32.dll&lt;br /&gt;EngineState: BREAKPOINTS 0&lt;br /&gt;EngineState: BREAKPOINTS 0&lt;br /&gt;EngineState: BREAKPOINTS 0&lt;br /&gt;Add Breakpoint: CODE 0 @ 71b6410c WS2_32!socket:0&lt;br /&gt;...&lt;br /&gt;EngineState: CURRENT_THREAD 0&lt;br /&gt;Hit Breakpoint: CODE 0 @ 71b6410c WS2_32!socket:0&lt;br /&gt;EngineState: EXECUTION_STATUS BREAK&lt;br /&gt;EngineState: EXECUTION_STATUS GO_HANDLED&lt;br /&gt;Change engine state to GO&lt;br /&gt;EngineState: EXECUTION_STATUS GO_HANDLED&lt;br /&gt;EngineState: EXECUTION_STATUS GO&lt;/blockquote&gt;Besides these expected events, we need another callback to process the exception.&lt;br /&gt;&lt;pre&gt;&lt;blockquote style="font-style: italic;"&gt;def onException(args):&lt;br /&gt; symbol = c.Symbols.GetNameByOffset(args.Address)&lt;br /&gt; sys.stdout.write("Exception: %08x %08x %s:%d" % (args.Code, args.Address, symbol[0], symbol[1]))&lt;br /&gt;&lt;br /&gt; if args.IsFirstChance:&lt;br /&gt;   print " first"&lt;br /&gt; else:&lt;br /&gt;   print " second"&lt;br /&gt;&lt;br /&gt; for frame in c.Control.GetStackFrames():&lt;br /&gt;   symbol = c.Symbols.GetNameByOffset(frame.InstructionOffset)&lt;br /&gt;   print " %04d %08x %s:%d" % (frame.FrameNumber, frame.InstructionOffset, symbol[0], symbol[1])&lt;br /&gt;&lt;br /&gt; print c.Control.Breakpoints&lt;br /&gt;&lt;br /&gt;c.EventCallbacks.Exception = onException&lt;/blockquote&gt;&lt;/pre&gt;The callback will log the exception information, and dump the caller  stack  with DebugControl.GetStackFrames() method, like&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;Exception: 000006ba 7c80bee7 kernel32!RaiseException:83 first&lt;br /&gt;0000 7c80bee7 kernel32!RaiseException:83&lt;br /&gt;0001 77c31e37 RPCRT4!RpcpRaiseException:36&lt;br /&gt;0002 77c32042 RPCRT4!NdrGetBuffer:70&lt;br /&gt;0003 77cb30e4 RPCRT4!NdrClientCall2:407&lt;br /&gt;0004 76e35039 DNSAPI!R_ResolverQuery:28&lt;br /&gt;0005 76e34f59 DNSAPI!Query_PrivateExW:391&lt;br /&gt;0006 76e3505f DNSAPI!DnsQuery_W:58&lt;br /&gt;0007 71a83f8e MSWSOCK!SaBlob_Query:45&lt;br /&gt;...&lt;br /&gt;0023 010045c5 ftp!main:1665&lt;br /&gt;0024 01006ee0 ftp!mainCRTStartup:303&lt;br /&gt;0025 7c82f23b kernel32!BaseProcessStart:35&lt;/blockquote&gt;Finally, we add a try...except to protect the WaitForEvent method, because some situation will raise exception&lt;br /&gt;&lt;pre&gt;&lt;blockquote style="font-style: italic;"&gt;try:&lt;br /&gt;while c.Control.WaitForEvent():&lt;br /&gt;    c.Control.ExecutionStatus = ExecutionStatus.GO_HANDLED&lt;br /&gt;    print "Change engine state to %s" % c.Control.ExecutionStatus&lt;br /&gt;except:&lt;br /&gt;if ExecutionStatus.NO_DEBUGGEE != c.Control.ExecutionStatus:&lt;br /&gt;    print "Unexpected error:", sys.exc_info()[0]&lt;br /&gt;    raise&lt;/blockquote&gt;&lt;/pre&gt;Now, its work, with less than one hundred code lines, and can be expand easy :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4121626987179262004-5047969000568949319?l=flierlu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flierlu.blogspot.com/feeds/5047969000568949319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4121626987179262004&amp;postID=5047969000568949319' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/5047969000568949319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/5047969000568949319'/><link rel='alternate' type='text/html' href='http://flierlu.blogspot.com/2007/05/write-debugger-in-5-minutes-with.html' title='Write a debugger in 5 minutes with PyDbgEng'/><author><name>Flier Lu</name><uri>http://www.blogger.com/profile/01953688425888938834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4121626987179262004.post-1821688310739891936</id><published>2007-05-26T15:19:00.000+08:00</published><updated>2007-05-26T15:48:11.062+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='debugging'/><title type='text'>Access the kernel space with PyDbgEng</title><content type='html'>One year ago, I wrote a Chinese article &lt;&lt;a href="http://www.blogcn.com/User8/flier_lu/blog/37101408.html"&gt;How to use &lt;span class="diary_title"&gt;kd/windbg engine to access the kernel space&lt;/span&gt;&lt;/a&gt;&gt;, now I port the implementation to the PyDbgExt project, so we can directly access the kernel space in python.&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;&gt;&gt;&gt; from PyDbgEng import *&lt;br /&gt;&gt;&gt;&gt; c = DebugClient()&lt;br /&gt;&gt;&gt;&gt; c.AttachKernel()&lt;br /&gt;&gt;&gt;&gt; c.Control.WaitForEvent()&lt;br /&gt;True&lt;br /&gt;&gt;&gt;&gt; c.Symbols.LoadedModules&lt;br /&gt;{'nt': (Module nt @ ffffffff80800000)}&lt;br /&gt;&gt;&gt;&gt; c.Symbols.GetSymbols("nt!KiServiceTable")&lt;br /&gt;{'KiServiceTable': ((Symbol nt!KiServiceTable), 0)}&lt;br /&gt;&gt;&gt;&gt; offset = c.Symbols.GetSymbols("nt!KiServiceTable").popitem()[1][0].Offset&lt;br /&gt;&gt;&gt;&gt; c.Symbols.GetSymbols(c.DataSpaces.Virtual.ReadPointers(offset)[0])&lt;br /&gt;{'NtAcceptConnectPort': ((Symbol nt!NtAcceptConnectPort), 18446744071571636794L)}&lt;br /&gt;&lt;/blockquote&gt;    To access the kernel mode, we must attach engine to the local kernel with AttachKernel() first, and  begin wait a debug event process with WaitForEvent(). For the kernel mode, this function will return immediately. After this, we can use almost all the functions to access the kernel space, such as modules or symbols.&lt;br /&gt;&lt;br /&gt;  Under the hood, to support this feature in a standalone python module, I use some dirty hack method, because the debug engine and driver disallow it used outside kd.exe or windbg.exe.&lt;br /&gt;  So, before call IDebugClient::AttachKernel method to enter the kernel mode, we must first hook four system functions:&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;  static DWORD WINAPI HookedGetModuleFileNameW(HMODULE hModule, LPWSTR lpFilename, DWORD nSize)&lt;br /&gt;{&lt;br /&gt;  DWORD dwSize = s_fnGetModuleFileNameW(hModule, lpFilename, nSize);&lt;br /&gt;&lt;br /&gt;  if (!hModule)&lt;br /&gt;  {&lt;br /&gt;    wchar_t *pch = wcsrchr(lpFilename, L'\\');&lt;br /&gt;    wcscpy_s(pch ? pch+1 : lpFilename, pch ? (nSize - (pch - lpFilename)) : nSize, L"kd.exe");&lt;br /&gt;    dwSize = wcslen(lpFilename);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return dwSize;&lt;br /&gt;}&lt;/blockquote&gt;&lt;ul&gt;&lt;li&gt;GetModuleFileNameW, debug engine use it to got the current executable filename, and check whether the filename end with "kd.exe" or "windbg.exe", but our filename maybe "python.exe"&lt;/li&gt;&lt;li&gt;FindResourceW, SizeofResource, LoadResource: debug engine use those functions to find and export the driver, which implement some internal works. I extract it from windbg.exe and embedded into PyDbgEng.dll.&lt;/li&gt;&lt;/ul&gt;    As the previous description mentioned, we embedded the driver "kldbgdrv.sys" to resource, which as type 0x7777 and id 0x4444, like&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;/////////////////////////////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;// RCDATA&lt;br /&gt;//&lt;br /&gt;&lt;br /&gt;30583   17476             "kldbgdrv.sys"&lt;/blockquote&gt;  This tech can be used in any program which wants to access the kernel mode :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4121626987179262004-1821688310739891936?l=flierlu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flierlu.blogspot.com/feeds/1821688310739891936/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4121626987179262004&amp;postID=1821688310739891936' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/1821688310739891936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/1821688310739891936'/><link rel='alternate' type='text/html' href='http://flierlu.blogspot.com/2007/05/access-kernel-space-with-pydbgeng.html' title='Access the kernel space with PyDbgEng'/><author><name>Flier Lu</name><uri>http://www.blogger.com/profile/01953688425888938834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4121626987179262004.post-3682782424385475797</id><published>2007-05-26T03:01:00.000+08:00</published><updated>2007-05-26T03:35:59.279+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='debugging'/><title type='text'>Dump Windows Service Table in WinDbg</title><content type='html'>&lt;blockquote&gt;&lt;/blockquote&gt;  &lt;span class="edgebig"&gt;&lt;a href="https://www.rootkit.com/user.php?name=buri"&gt;buri &lt;/a&gt;write a great article &lt;a href="https://www.rootkit.com/board.php?did=edge721&amp;closed=0&amp;amp;lastx=15"&gt;&lt;&lt;/a&gt;&lt;/span&gt;&lt;a href="https://www.rootkit.com/board.php?did=edge721&amp;closed=0&amp;amp;lastx=15"&gt;&lt;span class="edgeatitle"&gt;Windows Service Table Dumper for WinDbg&lt;/span&gt;&lt;/a&gt;&lt;span class="edgebig"&gt;&lt;a href="https://www.rootkit.com/board.php?did=edge721&amp;closed=0&amp;amp;lastx=15"&gt;&gt; &lt;/a&gt;show how to &lt;/span&gt;&lt;span class="edgeatext"&gt;use the built-in script language in WinDbg to do a real job: dump the windows service table.  But this script is short of readability, because the build-in script in WinDbg is very strange like its command design.&lt;br /&gt;   So, why we can't implement it more easy and readable, base on a friendly python script through &lt;a href="http://sourceforge.net/projects/pydbgext"&gt;PyDbgExt&lt;/a&gt;, my python extension for WinDbg :)&lt;br /&gt;&lt;br /&gt;   First we need define a script module, such as dumpServiceTable.py, which includes a function dumpServiceTable to dump that table, and import the dependence modules&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;from PyDbgEng import *&lt;br /&gt;from struct import *&lt;br /&gt;&lt;br /&gt;c = DebugClient.Current&lt;br /&gt;s = c.Symbols&lt;br /&gt;v = c.DataSpaces.Virtual&lt;/blockquote&gt;   Next, we got the common base object, such as DebugClient.Current which is the current debug session in windbg; Symbols and DataSpaces.Virtual will support us query the debug symbol and read/write the virtual address space.&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;def getSymbol(name):&lt;br /&gt;    return s.GetSymbols(name).popitem()[1][0]&lt;br /&gt;&lt;br /&gt;def getSymbol(offset):&lt;br /&gt; return s.GetSymbols(offset).popitem()[1][0]&lt;br /&gt;&lt;br /&gt;def readDWORD(offset):&lt;br /&gt; return unpack_from("L", v.Read(offset, 4))[0]&lt;/blockquote&gt;&lt;br /&gt;   To make the code more readable, we define some utility functions: getSymbol can get the symbol object with its name or offset; readDWORD read unsigned long from the offset. According to the result type of VirtualDataSpace.Read function is a buffer object, we need use unpack_from function to decode the buffer.&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;def dumpServiceTable():&lt;br /&gt;    KiServiceTable = getSymbol("nt!KiServiceTable")&lt;br /&gt;    KiServiceLimit = getSymbol("nt!KiServiceLimit")&lt;br /&gt;&lt;br /&gt;    idx = 0&lt;br /&gt;&lt;br /&gt;    for addr in v.ReadPointers(KiServiceTable.Offset,  readDWORD(KiServiceLimit.Offset)):&lt;br /&gt;        try:&lt;br /&gt;                 symbol = getSymbol(addr)&lt;br /&gt;   &lt;br /&gt;                 symbolName = "%s!%s" % (symbol.Module.ModuleName, symbol.Name)&lt;br /&gt;           except:&lt;br /&gt;                 symbolName = "&lt;unknown&gt;"&lt;br /&gt;   &lt;br /&gt;           print "%03d %08x %s" % (idx, addr &amp; 0xFFFFFFFF, symbolName)&lt;br /&gt; &lt;br /&gt;           idx = idx + 1&lt;/unknown&gt;&lt;/blockquote&gt;     The last part of code read and dump the service table:&lt;br /&gt;&lt;/span&gt;&lt;ol&gt;&lt;li&gt;get the symbol object of &lt;span class="edgeatext"&gt;nt!KiServiceTable and &lt;/span&gt;&lt;span class="edgeatext"&gt;nt!KiServiceLimit&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="edgeatext"&gt;read a group of pointers from the begin of table&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="edgeatext"&gt;try to get the symbol object for every entry in table&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="edgeatext"&gt;if the symbol exists, dump it's address, module and name&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="edgeatext"&gt;if the symbol nonexists, just show warning. we can provide more information about this in future&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;    Finally, we load the script to windbg and execute it :)&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;lkd&gt; .extpath+ D:\Study\Win32\PyDbgExt\Binary\debug&lt;br /&gt;Extension search path is: ...;D:\Study\Win32\PyDbgExt\Binary\debug&lt;br /&gt;lkd&gt; .load PyDbgExt&lt;br /&gt;lkd&gt; .chain&lt;br /&gt;Extension DLL search Path:&lt;br /&gt;   ...&lt;br /&gt;Extension DLL chain:&lt;br /&gt;   PyDbgExt: API 1.0.0, built Sat May 26 02:17:49 2007&lt;br /&gt;       [path: D:\Study\Win32\PyDbgExt\Binary\debug\PyDbgExt.dll]&lt;br /&gt;   dbghelp: image 6.7.0005.0, API 6.0.6, built Fri Mar 30 02:08:09 2007&lt;br /&gt;       [path: D:\MS\Debugging Tools for Windows\dbghelp.dll]&lt;br /&gt;   ...&lt;br /&gt;lkd&gt; !import dumpServiceTable&lt;br /&gt;Import &lt;module&gt; succeeded.&lt;br /&gt;lkd&gt; !eval dumpServiceTable.dumpServiceTable()&lt;br /&gt;000 8092023a nt!NtAcceptConnectPort&lt;br /&gt;001 8096b71e nt!NtAccessCheck&lt;br /&gt;002 8096f9be nt!NtAccessCheckAndAuditAlarm&lt;br /&gt;...&lt;br /&gt;032 808b9810 nt!NtCompressKey&lt;br /&gt;033 f4bed0d2 &lt;unknown&gt;&lt;br /&gt;034 8088d0c8 nt!NtContinue&lt;br /&gt;...    &lt;/unknown&gt;&lt;/module&gt;&lt;/blockquote&gt;    If there some wrong in script, just edit it and reload it with python build-in function&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;lkd&gt; !eval reload(dumpServiceTable)&lt;br /&gt;&lt;module&gt;&lt;/module&gt;&lt;/blockquote&gt;    Enjoy it :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4121626987179262004-3682782424385475797?l=flierlu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flierlu.blogspot.com/feeds/3682782424385475797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4121626987179262004&amp;postID=3682782424385475797' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/3682782424385475797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/3682782424385475797'/><link rel='alternate' type='text/html' href='http://flierlu.blogspot.com/2007/05/dump-windows-service-table-in-windbg.html' title='Dump Windows Service Table in WinDbg'/><author><name>Flier Lu</name><uri>http://www.blogger.com/profile/01953688425888938834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4121626987179262004.post-6132234293886010529</id><published>2007-05-16T17:30:00.000+08:00</published><updated>2007-05-16T17:42:53.267+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='virtualization'/><category scheme='http://www.blogger.com/atom/ns#' term='software'/><title type='text'>An alternative open source virtualization solution: VirtualBox</title><content type='html'>To accelerate the product development and test, we usual choose some kinds  of &lt;a href="http://www.virtualbox.org/wiki/Virtualization"&gt;virtualizer&lt;/a&gt; to  simulate environment, such as &lt;a href="http://www.vmware.com/products/ws/"&gt;VMware workstation&lt;/a&gt;, &lt;a href="http://www.microsoft.com/windows/products/winfamily/virtualpc/default.mspx"&gt;Virtual  PC &lt;/a&gt;etc. With these kinds of VM, we can build the environment one time, and  reuse it again and again, just take snapshot and rollback it.&lt;span class="Normal"&gt; &lt;p&gt;   But if we have some advance requirement, such as control the VM to  implement some auto-test script, these commercial products maybe restrict your  idea. Even they provided some SDK, the ability is very limited.&lt;/p&gt; &lt;p&gt;   Fortunately we have some alternative virtualization solutions, such as &lt;a href="http://www.virtualbox.org/wiki/VirtualBox"&gt;VirtualBox&lt;/a&gt;. It is a  general-purpose full &lt;a class="wiki" href="http://www.virtualbox.org/wiki/Virtualization"&gt;virtualizer&lt;/a&gt; for x86  hardware. Targeted at server, desktop and embedded use, it is now the only  professional-quality virtualization solution that is also Open Source  Software.&lt;/p&gt; &lt;p&gt;   The usage and &lt;a href="http://www.virtualbox.org/wiki/Screenshots"&gt;GUI&lt;/a&gt;  of VirtualBox is very like VMware, so we can switch to it easy. The VirtualBox  can be &lt;a href="http://www.virtualbox.org/wiki/Downloads"&gt;downloaded&lt;/a&gt; and  installed on Windows, Linux and OS X hosts; And the guest OS can support mostly  common platform, such as Windows, Linux, xxxBSD, etc. A complete guest OS  list can be found at &lt;a href="http://www.virtualbox.org/wiki/Guest_OSes"&gt;Guest  OSes&lt;/a&gt;. It also has an &lt;a href="http://www.virtualbox.org/wiki/Editions"&gt;open  source edition&lt;/a&gt; under the GPL license, but it isn't including some advance  features, such as RDP support.&lt;/p&gt; &lt;p&gt;   Compare with VMware or other VM vender, VirtualBox has a great openness.  It's virtual machine descriptions in XML, we can easy fetch information from it;  It's VM directly support RDP (&lt;a href="http://msdn2.microsoft.com/en-us/library/aa383015.aspx"&gt;Remote Desktop  Protocol&lt;/a&gt;) protocol, so we can use &lt;a href="http://www.microsoft.com/windowsxp/downloads/tools/rdclientdl.mspx"&gt;remote  desktop connection software&lt;/a&gt; to control it, the latest version of VMware -  Workstation 6.0 provide similar feature which allow remotely access the console  of a VM from a VNC client.&lt;/p&gt; &lt;p&gt;   Furthermore, the most important difference is VirtualBox provided a very  powerful management interface. For end-users, they can use VBoxManage in command  line to control most common functions of VM; for developers, they can get some  depth control with a set of &lt;a href="http://www.virtualbox.org/browser/trunk/src/VBox/Main/idl/VirtualBox.xidl"&gt;COM/XPCOM  control interfaces&lt;/a&gt;, such as control the keyboard/mouse action etc.&lt;/p&gt; &lt;p&gt;   From the implementation viewpoint, the architecture of VirtualBox much  likes a client/server solution. The controller client, such as QT-based GUI or  console mode VBoxManage, connects to the backend VM implementation (VBoxVMM,  etc.), through COM/XPCOM interface (VBoxSVC, VBoxC, etc).&lt;/p&gt; &lt;p&gt;   In addition, a kernel driver (VBoxDrv.sys on Windows) or module (vboxdrv  on Linux) will allocating physical memory for the VM, control the context switch  and other dirty work.&lt;/p&gt; &lt;p&gt;  But not like &lt;a href="http://kb.xensource.com/entry.jspa?externalID=203"&gt;Xen&lt;/a&gt; and &lt;a href="http://www.vmware.com/company/news/releases/intel_virtualization.html"&gt;VMware&lt;/a&gt;,  VirtualBox is not directly depending on some kinds of hardware virtualization  technology, such as &lt;a href="http://www.intel.com/technology/virtualization/index.htm"&gt;VT &lt;/a&gt;or &lt;a href="http://www.amd.com/us-en/Processors/ProductInformation/0,,30_118_8796_14287,00.html"&gt;AMD-V&lt;/a&gt;.  VirtualBox run the guest OS kernel at ring 1, through some advanced code  scanning, analysis and patching techniques, such as "Patch Manager" (PATM) and  "Code Scanning and Analysis Manager" (CSAM).&lt;/p&gt; &lt;blockquote dir="ltr" style="margin-right: 0px;"&gt; &lt;p&gt;&lt;em&gt; Before executing ring 0 code, we scan it recursively to discover  problematic instructions. We then perform in-situ patching, i.e. we replace the  instruction with a jump to hypervisor memory where an integrated code generator  has placed a more suitable implementation. In reality, this is a very complex  task as there are lots of odd situations to be discovered and handled correctly.  So, with its current complexity, one could argue that PATM is an advanced  in-situ recompiler. &lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;In addition, every time a fault occurs, we analyze the fault's cause to  determine if it is possible to patch the offending code to prevent it from  causing more expensive faults in the future. This turns out to work very well,  and we can reduce the faults caused by our virtualization to a rate that  performs much better than a typical recompiler, or even VT-x technology, for  that matter.&lt;/em&gt; &lt;/p&gt;&lt;/blockquote&gt; &lt;p dir="ltr" style="margin-right: 0px;"&gt;   This method seems specially but  effective, at least on my machine, VirtualBox run some OS correctly and very  fast. &lt;/p&gt; &lt;p dir="ltr"&gt;   If you have more detail question, please refer to their &lt;a href="http://www.virtualbox.org/wiki/Developer_FAQ"&gt;Developer FAQ&lt;/a&gt; or  directly read the &lt;a href="http://www.virtualbox.org/wiki/Source_code_organization"&gt;source code&lt;/a&gt;.  :)&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4121626987179262004-6132234293886010529?l=flierlu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://flierlu.blogspot.com/feeds/6132234293886010529/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4121626987179262004&amp;postID=6132234293886010529' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/6132234293886010529'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4121626987179262004/posts/default/6132234293886010529'/><link rel='alternate' type='text/html' href='http://flierlu.blogspot.com/2007/05/alternative-open-source-virtualization.html' title='An alternative open source virtualization solution: VirtualBox'/><author><name>Flier Lu</name><uri>http://www.blogger.com/profile/01953688425888938834</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
