{"id":91341,"date":"2015-10-16T07:00:00","date_gmt":"2015-10-16T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20151016-00\/?p=91341\/"},"modified":"2019-03-13T12:20:41","modified_gmt":"2019-03-13T19:20:41","slug":"20151016-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20151016-00\/?p=91341","title":{"rendered":"I have the handle to a file; how can I get the file name from the debugger?"},"content":{"rendered":"<p>Suppose you&#8217;re debugging and you find yourself with the handle to a file, and you would like to know what file that handle corresponds to. <\/p>\n<p>Well, the way you would do this from code is to <a HREF=\"http:\/\/msdn.microsoft.com\/library\/aa366789\">call <code>Get&shy;Final&shy;Path&shy;Name&shy;By&shy;Handle<\/code><\/a>, but you&#8217;re not in code; you&#8217;re in the debugger. <\/p>\n<p>But you can simulate what code did from the debugger. <\/p>\n<p>Now, if <code>Get&shy;Final&shy;Path&shy;Name&shy;By&shy;Handle<\/code> were a function you had written, you could just <a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2007\/04\/27\/2292037.aspx\">use the <code>.call<\/code> command<\/a> to ask the debugger to build a call frame and call the function and then clean up. But since you didn&#8217;t write that function, you&#8217;ll have to build the call frame manually. <\/p>\n<p>Let&#8217;s say the handle you are interested is 0x5CC. <\/p>\n<pre>\n0:000&gt; !handle 5cc f\nHandle 5cc\n  Type          File\n  Attributes    0\n  GrantedAccess 0x120089:\n         ReadControl,Synch\n         Read\/List,ReadEA,ReadAttr\n  HandleCount   2\n  PointerCount  262145\n  No Object Specific Information available\n<\/pre>\n<p>Yup, it&#8217;s a file. Let&#8217;s see what file it is. First, the x86 way. We start by recording the contents of the volatile registers so that we can restore them afterwards. <\/p>\n<pre>\n0:000&gt; r\neax=00000925 ebx=00000003 ecx=267ad2be edx=00000000 esi=00000000 edi=00b300e0\neip=00b36e1d esp=0089f7cc ebp=0089f838 iopl=0         nv up ei pl zr na pe nc\ncs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00200246\ncontoso!CContoso::OnCommand+0x1a5:\n00b36e1d 8bd1            mov     edx,ecx\n<\/pre>\n<p>Next, we allocate some memory to hold the result. <\/p>\n<pre>\n0:000&gt; .dvalloc 1000\nAllocated 1000 bytes starting at 05740000\n<\/pre>\n<p>Next, we build the function call. Since this is x86, all parameters go on the stack, and the stdcall calling convention pushes the last parameter first. <\/p>\n<pre>\n; simulate \"push dwFlags\"\n0:000&gt; r esp=esp-4;ed esp 0\n; simulate \"push cchFilePath\"\n0:000&gt; r esp=esp-4;ed esp 0x800\n; simulate \"push lpszFilePath\"\n0:000&gt; r esp=esp-4;ed esp 05740000\n; simulate \"push hFile\"\n0:000&gt; r esp=esp-4;ed esp 5cc\n; simulate \"call kernelbase!GetFinalPathNameByHandleW\"\n0:000&gt; r esp=esp-4;ed esp eip\n0:000&gt; r eip=kernelbase!GetFinalPathNameByHandleW\n; execute until the function returns\n0:000&gt; g poi esp\neax=00000025 ebx=00000003 ecx=7715fb62 edx=00000046 esi=00000000 edi=00b300e0\neip=00b36e1d esp=0089f7cc ebp=0089f838 iopl=0         nv up ei pl zr na pe cy\ncs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00200247\ncontoso!CContoso::OnCommand+0x1a5:\n00b36e1d 8bd1            mov     edx,ecx\n<\/pre>\n<p>Okay, we&#8217;ve returned. We see that <code>eax<\/code> is nonzero, so the call succeeded. Let&#8217;s look at the output buffer. <\/p>\n<pre>\n0:000&gt; du 05740000\n05740000  \"\\\\?\\C:\\Users\\Public\\Documents\\lo\"\n05740040  \"g.txt\"\n<\/pre>\n<p>There&#8217;s our path to the file, which looks like a log file. <\/p>\n<p>Now we have to play Boy Scout and leave things the way we found them. <\/p>\n<pre>\n; do not need to restore stack pointer since stdcall is callee-clean\n0:000&gt; r eax=925\n0:000&gt; r ecx=267ad2be\n0:000&gt; r edx=0\n0:000&gt; r efl=200246\n0:000&gt; r\neax=00000925 ebx=00000003 ecx=267ad2be edx=00000000 esi=00000000 edi=00b300e0\neip=00b36e1d esp=0089f7cc ebp=0089f838 iopl=0         nv up ei pl zr na pe nc\ncs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00200246\ncontoso!CContoso::OnCommand+0x1a5:\n00b36e1d 8bd1            mov     edx,ecx\n<\/pre>\n<p>Most of the registers are preserved by the function call, but we need to restore the volatile registers <code>eax<\/code>, <code>ecx<\/code>, <code>edx<\/code>, and flags. <\/p>\n<p>In practice, you may be able to get away with not restoring everything. For example, flags may not be meaningful at the point in the code you broke in. And if you broke in immediately after a function call or immediately on entry to a function, the values in the nonvolatile registers are already trashed or trashable, so you don&#8217;t need to restore them either. <\/p>\n<p>Next up is x64. This is harder because of the shadow space and many more registers. Again, we start by recording the contents of the volatile registers so that we can restore them afterwards. <\/p>\n<pre>\n0:000&gt; r\nrax=0000000000000a0c rbx=0000000000000000 rcx=230fe38816f90000\nrdx=0000000000000000 rsi=0000000000000000 rdi=0000000080004005\nrip=000007f709e471fc rsp=0000002e45a9f880 rbp=0000002e45a9f949\n r8=0000000000000000  r9=000007fbab8aabd0 r10=0000000000000003\nr11=0000002e45a9f2a8 r12=0000000000000000 r13=0000000000000001\nr14=ffffffffffffffff r15=0000000000000000\niopl=0         nv up ei pl nz na po cy\ncs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000207\ncontoso!CContoso::OnCommand+0x3b9:\n000007f7`09e471fc 33c0            xor     eax,eax\n<\/pre>\n<p>Next, we allocate some memory to hold the result. <\/p>\n<pre>\n0:000&gt; .dvalloc 1000\nAllocated 1000 bytes starting at 0000002e`475e0000\n<\/pre>\n<p>Next, we build the function call. On x64, the first four parameters go into registers <code>rcx<\/code>, <code>rdx<\/code>, <code>r8<\/code>, and <code>r9<\/code>, and corresponding shadow space is reserved on the stack. <\/p>\n<pre>\n; create shadow space\n0:000&gt; r rsp=@rsp-20\n; first parameter is hFile\n0:000&gt; r rcx=5cc\n; second parameter is lpszFilePath\n0:000&gt; r rdx=0000002e`475e0000\n; third parameter is cchFilePath\n0:000&gt; r r8=800\n; fourth parameter is dwFlags\n0:000&gt; r r9=0\n; simulate \"call kernelbase!GetFinalPathNameByHandleW\"\n0:000&gt; r rsp=@rsp-8; ep rsp @rip\n0:000&gt; r rip=kernelbase!GetFinalPathNameByHandleW\n; execute until the function returns\n0:000&gt; g poi @rsp\n0:000&gt; r\nrax=0000000000000025 rbx=0000000000000000 rcx=00000000ffffffff\nrdx=0000000000008000 rsi=0000000000000000 rdi=0000000080004005\nrip=000007f709e471fc rsp=0000002e45a9f860 rbp=0000002e45a9f949\n r8=0000002e4a159390  r9=000007fbab91a3a0 r10=0000000000000003\nr11=0000002e45a9f3a8 r12=0000000000000000 r13=0000000000000001\nr14=ffffffffffffffff r15=0000000000000000\niopl=0         nv up ei pl nz na po nc\ncs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206\ncontoso!CContoso::OnCommand+0x3b9:\n000007f7`09e471fc 33c0            xor     eax,eax\n<\/pre>\n<p>Again, we look at the result. <\/p>\n<pre>\n0:000&gt; du 0000002e`475e0000\n0000002e`475e0000  \"\\\\?\\C:\\Users\\raymondc\\Desktop\\lo\"\n0000002e`475e0040  \"g.txt\"\n<\/pre>\n<p>And again, we need to undo everything we did so the application doesn&#8217;t freak out. <\/p>\n<pre>\n0:000&gt; r rsp=@rsp+20\n0:000&gt; r rax=0a0c\n0:000&gt; r rcx=230fe38816f90000\n0:000&gt; r rdx=0\n0:000&gt; r r8=0\n0:000&gt; r r9=7fbab8aabd0\n0:000&gt; r r10=3\n0:000&gt; r r11=2e45a9f2a8\n0:000&gt; r efl=207\n0:000&gt; r\nrax=0000000000000a0c rbx=0000000000000000 rcx=230fe38816f90000\nrdx=0000000000000000 rsi=0000000000000000 rdi=0000000080004005\nrip=000007f709e471fc rsp=0000002e45a9f880 rbp=0000002e45a9f949\n r8=0000000000000000  r9=000007fbab8aabd0 r10=0000000000000003\nr11=0000002e45a9f2a8 r12=0000000000000000 r13=0000000000000001\nr14=ffffffffffffffff r15=0000000000000000\niopl=0         nv up ei pl nz na po cy\ncs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000207\ncontoso!CContoso::OnCommand+0x3b9:\n000007f7`09e471fc 33c0            xor     eax,eax\n<\/pre>\n<p>Again, most of the registers are preserved by the function call, but we need to restore the volatile registers <code>eax<\/code>, <code>ecx<\/code>, <code>edx<\/code>, <code>r8<\/code> through <code>r11<\/code>, and flags. <\/p>\n<p><b>Exercise<\/b>: I could&#8217;ve skipped restoring <code>rax<\/code> and flags. Why? <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Build the call on the stack.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-91341","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Build the call on the stack.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/91341","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=91341"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/91341\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=91341"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=91341"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=91341"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}