From 9e57e58b88019f9ba06bddde389821692a6fc3f4 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Tue, 6 Jul 2010 14:49:02 +0000 Subject: [PATCH] git-svn-id: https://pykd.svn.codeplex.com/svn@50344 9b283d60-5439-405e-af05-b73fd8c4d996 --- kdar/cmd.py | 5 + kdar/drvobj.py | 11 + kdar/idt.py | 62 ++++++ pykd.sln | 30 +++ pykd.suo | Bin 0 -> 64512 bytes pykd/dbgcmd.cpp | 127 ++++++++++++ pykd/dbgcmd.h | 16 ++ pykd/dbgexcept.h | 16 ++ pykd/dbgext.cpp | 143 +++++++++++++ pykd/dbgmem.cpp | 92 +++++++++ pykd/dbgmem.h | 14 ++ pykd/dbgmodule.cpp | 84 ++++++++ pykd/dbgmodule.h | 58 ++++++ pykd/dbgprint.cpp | 16 ++ pykd/dbgprint.h | 15 ++ pykd/dbgreg.cpp | 62 ++++++ pykd/dbgreg.h | 13 ++ pykd/dbgsym.cpp | 105 ++++++++++ pykd/dbgsym.h | 16 ++ pykd/dbgsystem.cpp | 33 +++ pykd/dbgsystem.h | 14 ++ pykd/dbgtype.cpp | 266 ++++++++++++++++++++++++ pykd/dbgtype.h | 41 ++++ pykd/pykd.cpp | 0 pykd/pykd.def | 6 + pykd/pykd.suo | Bin 0 -> 7680 bytes pykd/pykd.vcproj | 488 +++++++++++++++++++++++++++++++++++++++++++++ pykd/stdafx.cpp | 8 + pykd/stdafx.h | 35 ++++ test/print.py | 8 + test/regs.py | 16 ++ test/type.py | 13 ++ 32 files changed, 1813 insertions(+) create mode 100644 kdar/cmd.py create mode 100644 kdar/drvobj.py create mode 100644 kdar/idt.py create mode 100644 pykd.sln create mode 100644 pykd.suo create mode 100644 pykd/dbgcmd.cpp create mode 100644 pykd/dbgcmd.h create mode 100644 pykd/dbgexcept.h create mode 100644 pykd/dbgext.cpp create mode 100644 pykd/dbgmem.cpp create mode 100644 pykd/dbgmem.h create mode 100644 pykd/dbgmodule.cpp create mode 100644 pykd/dbgmodule.h create mode 100644 pykd/dbgprint.cpp create mode 100644 pykd/dbgprint.h create mode 100644 pykd/dbgreg.cpp create mode 100644 pykd/dbgreg.h create mode 100644 pykd/dbgsym.cpp create mode 100644 pykd/dbgsym.h create mode 100644 pykd/dbgsystem.cpp create mode 100644 pykd/dbgsystem.h create mode 100644 pykd/dbgtype.cpp create mode 100644 pykd/dbgtype.h create mode 100644 pykd/pykd.cpp create mode 100644 pykd/pykd.def create mode 100644 pykd/pykd.suo create mode 100644 pykd/pykd.vcproj create mode 100644 pykd/stdafx.cpp create mode 100644 pykd/stdafx.h create mode 100644 test/print.py create mode 100644 test/regs.py create mode 100644 test/type.py diff --git a/kdar/cmd.py b/kdar/cmd.py new file mode 100644 index 0000000..b43f101 --- /dev/null +++ b/kdar/cmd.py @@ -0,0 +1,5 @@ +from pykd import * + +s = dbgCommand( "dt nt!_DRIVER_OBJECT" ) + +dprintln( s ) \ No newline at end of file diff --git a/kdar/drvobj.py b/kdar/drvobj.py new file mode 100644 index 0000000..9b60816 --- /dev/null +++ b/kdar/drvobj.py @@ -0,0 +1,11 @@ +from pykd import * + + +drvObj = typedVar( "nt", "_DRIVER_OBJECT", addr64( 0x82000c08 ) ) + +dprintln( "DriverName.Length = %(1)d" % { "1" : drvObj.DriverName.Length } ) + +for i,f in drvObj.MajorFunction.iteritems(): + + dprintln( "MajorFunction[%(1)d] = " % { "1" : i } + findSymbol( addr64( f ) ) ) + diff --git a/kdar/idt.py b/kdar/idt.py new file mode 100644 index 0000000..5f8e2b3 --- /dev/null +++ b/kdar/idt.py @@ -0,0 +1,62 @@ +from pykd import * + + +if not is64bitSystem(): + + dprintln( "check interrupt handlers...\n" ) + + idtr = reg( "idtr" ) + + nt = loadModule( "nt" ) + nt.KiInterruptDispatch = getOffset( "nt", "KiInterruptDispatch" ) + nt.KiChainedDispatch = getOffset( "nt", "KiChainedDispatch" ) + nt.KiInterruptTemplate = getOffset( "nt", "KiInterruptTemplate" ) + + hal = loadModule( "hal" ) + + + ErrorCount = 0 + + for i in range(0,255): + + idtEntry = typedVar( "nt", "_KIDTENTRY", idtr + i*8 ) + + if idtEntry.Selector == 8: + + InterruptHandler = ( idtEntry.ExtendedOffset * 0x10000 ) + idtEntry.Offset + + if InterruptHandler != 0 and not nt.contain( InterruptHandler ) and not hal.contain( InterruptHandler ): + + kinterrupt = containingRecord( InterruptHandler, "nt", "_KINTERRUPT", "DispatchCode" ) + + dprintln ( "KINTERRUPT: %(1)x" % { "1" : kinterrupt.getAddress() } ) + + if addr64( kinterrupt.DispatchAddress ) != nt.KiInterruptDispatch and addr64( kinterrupt.DispatchAddress ) != nt.KiChainedDispatch: + dprintln ( "Threat!!! KINTERRUPT::DispatchAddress PATCHED" ) + ErrorCount += 1 + + if findModule( kinterrupt.ServiceRoutine ) == None: + dprintln ( "Threat!!! KINTERRUPT::ServiceRoutine (%(1)x) out of any module" % { "1" : kinterrupt.ServiceRoutine } ) + ErrorCount += 1 + + if not compareMemory( nt.KiInterruptTemplate, InterruptHandler, 98 ): + dprintln ( "Threat!!! KINTERRUPT::DispatchCode area PATCHED" ) + ErrorCount += 1 + + + dprintln ( "" ) + + + dprintln( "check end: %(1)d threats" % { "1" : ErrorCount } ) + + +else: + + dprintln( "x64 is not supported" ) + + + + + + + diff --git a/pykd.sln b/pykd.sln new file mode 100644 index 0000000..9a06613 --- /dev/null +++ b/pykd.sln @@ -0,0 +1,30 @@ +п»ї +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pykd", "pykd\pykd.vcproj", "{C0A12E93-4B76-4B17-B837-37020F957AD2}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C0A12E93-4B76-4B17-B837-37020F957AD2}.Debug|Win32.ActiveCfg = Debug|Win32 + {C0A12E93-4B76-4B17-B837-37020F957AD2}.Debug|Win32.Build.0 = Debug|Win32 + {C0A12E93-4B76-4B17-B837-37020F957AD2}.Debug|x64.ActiveCfg = Debug|x64 + {C0A12E93-4B76-4B17-B837-37020F957AD2}.Debug|x64.Build.0 = Debug|x64 + {C0A12E93-4B76-4B17-B837-37020F957AD2}.Release|Win32.ActiveCfg = Release|Win32 + {C0A12E93-4B76-4B17-B837-37020F957AD2}.Release|Win32.Build.0 = Release|Win32 + {C0A12E93-4B76-4B17-B837-37020F957AD2}.Release|x64.ActiveCfg = Release|x64 + {C0A12E93-4B76-4B17-B837-37020F957AD2}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/pykd.suo b/pykd.suo new file mode 100644 index 0000000000000000000000000000000000000000..e3a1c78d8867f60cf1a54387f20591c5000e0807 GIT binary patch literal 64512 zcmeI537B0)mB(L`5CSUuW>{=O2nmFcq&rCyV#po{1Of>G@j=t+?rd~AvAeTDKn7GI zE;!(fh|9R3qRt?=jyfvh2BQc%&WMf*DlYhq%Y5Pt-+*NPzgty(m-pVi_1=B2)6rCa zr|-RW>(!|`b?VfqQ>W@a_UK_xzW4qyKP@D}oWh903%d_2jEcnXr~4-Nd}yJ-^GLx9 zyLaz)(Ve={Btf`bGv7Q94ou;56+Ap)^L;V{AB zf+GY+362pQEjU(irr@Q5;{=lg#|usnoG5sipjmK|V65O|!8pNqL5tul!34o6Ah<-ZOmLy#BEfRO#ex-rZox{yrGiz0%LK0wyi#z5peWcZXcue{ zbP28&bO8eM6Nt-4+#SSwg3STE=iTqU?tuu;$}*d(}Iz;9g`(DN3-HXFZP*Bydu z1=k673Zm)x-6hItQ(-`Du}Jw26#9Z+D4}OKT3qAs!xw4czOURqcFYOiY#O0Nb0M(8 za$(#gikv6xYjn4$K&k!1(UL+AKUd#h!n=f(YJq-H`~p$BU-iFK|GQNt7vFD^Rs27$ zuwN5=@5)dyVdO=V?&)8I%hjSiqC!WZQ>ExoyLXGXHmfA-MU7sSCOv?kzE}-@f8;<^2GIYYA!%Lzr~RP?eH1xxtbqQHY(WN;>;Lpw*Z;|j zK7F4cS{C|0&#$ppWC71p?DbY%TLi5F`m2)%ZMr8NGJq?xge(1@>s(#GBB1~Cj9lSL z|L02o=ekr^`ak`i{(re3+W(OYq+6*g{eM6}|0j;VO#ep?@Jt`(`Z`^&7P$W3Y2%S2 zyr=(jrT=rKzas}+|L@cNX2GijyoXP27SR8ZAx;KF`#l>3k{M!+ToT|bf7Qi9-0{l3pb5?P4-=+=4%{#8?3ja;+>P9jaM$PWs($ho3 zNmMVGRb1Y;X>DJ}#^%NJr96S(!8Y>SL=668Z>KE+^&&rMq#4LwoLJzL7Dp{E!K$hnl<_$$+qa1 zJ$hQ9xGky&(xh3xE9(6M{pVK$x-L|%tCeDHAbI-4w;hV_)Yt>I?9eRvBevR2ALp9= zi-I&uqeGB3iGRMz)vYpIqZZhtQZpu{m1BbB|0v~yZ1TlVn@tc9lK2^aI#mK+2|Ql) zr#{F_U;MN+vXzj;PfPczy;i99TSN=Wk`}-ZUh?zB54|3u(<$@^IEuR4B^WC1gU5Qr z*=tn4;$Ruv^KdAODdC=_3!Km?I?;c-MJK~Goq?p%gF;jA-!^4%@BaD5Rp!4PYM<5O zLPnj+LHrl+9lS@VoHBgFIOLv^_?M}s8-*1;^fKEQHfc1gBm*W{{(p%w^u>?9#8^$B zzYhp!pJ|5%0jqu|IyJo+g*Eg_noXX=G~ zjmD!714ks{^%&^Pj0e&5lk_}Ski>hK;+CoXdxBPGwC)fuGG=ccoEtG~WsG4K+p7Q9 zi5sVA<~miH_9D%cTQoCnl@>cwH8yusb$^Cp+VqY){!dZrDdO+5G|!!>UoX`2^{M>l z=0XbtouDHqLGs^Z@gMC4EqwW(I#05V$vB6Eb3AVP*&1>ETE(LOxHn16=2`uJute^+{&%7xeDR;8v^Uud7O3{jK>Gu|ty_|= zlB97M<5$i90(%SM#20^5{!Z4|vMtaOL%uWf&nVZ?1IqKJk&dJt9oTN_$(v^f)|z_e zI9WEFZc!W!lX?D5N&gw@JCmh}%nx`C&3C?1bg9N+uRBLijV*_f`z`8|S!Fr9?qvzb zU|)K?e6S2F3gce%=Xs~U>C5Nd|HF?wdc+4VJLH1G!4Hq=dH%qYFM7-FTb_ON!MhhJ zvF6XeI`Wk7e(dCvmwfscKfV6c)f*9H3M&e2YmR*Ig$GZ(;O=*I-TSr^e}7hWzc;zm z{{P};Y>bs>f8jjP-A&f~x>M5G%oL3dR(lTP#BEsMu8{^n54=Wv$sBHq{-%l-_)nNB z%VDdY+66`N=X%Mle%)RE=t05ztluYpM{Neg>rTr-58AAJ(Y(-xOm9cuNe|ec7y~t= zddr`2O8YIF?WNMEz}gY$xLt$gF>Q08l^~54lRk2p{d$}29`uuTC5F(6LM=o!E(5k5K=>oJX0`zb+K*L4H^`XCO2}b*Fjdfa^x%8K)>Lt?0x8L(y!tv_= zln9$jvIe{_7se}cf_>ra?9TqaB4`UVU}i<>wjZ*nh5t|0@6hK7tHk#!)h_gTX1m+f z|LFN!)%UV&FZ>?)vqD$f{k-H4a{=f@NbCR8O_J3A&i;0aQu)$EG)a05XuJ$fo?CQ=B1 z`FnJ}q{qP!ji=nNw{N2HFf(}(qVZ>oIhWWj6OBiz&jK%3KAK(!0ZoHA)_0Id+|Q~JKQwsa-nN@{u{7w`2oXv}){cC} z7C-u%`ZKD51KfWe|NVD{xVbZHxi8k$^a(d6bgRwKM);kf+2Kkv$Buv1)ZgKEwBPag zmS@46?6;22XX+j0ASP&scKnAtb^M3U4pj(@H3Y`-FU>C$zAeC}6P1g+hia_< zCgXWWNX8>`fN1=Kdj5{!ghV{lpCIV9{V?Q+IDN{^ncUn5oi8cRmE~ZFmIDh&vmlwC zG5UM~G>fL+AY$DpI6e^%ozOp^E9tA%InVjgQvu(&woo=fa9m3{p*w-Hk`7xWV;6yO z#Kj?Fp*PwzakLe7P~xCBanKpt7IDo2_gklxBM*ohD>y|!m?$9bB*AF{0FZiGc2Y?o{|772P~yK?2aRduCB_#ckHEAKh= zd*FBV;2v2(9jGsSh<-9dKplyL7Di$loyNs&$jv{r2CMW~Pgtchx*qlE2>2=FncH@+ zfSj>%ud9iEZX|0ToQG%A-=sk2j#4^p{xOxpW&}6?Kz2miBkgDK(_)(-4ga*XOzb=1 z5AcGU;PI2dNANcu_**kdKT-r5atO@w>A8 zVBSed@sTNNHG@^7%?XJTN{=7z{J)=55>whsy!(GT{xuQ#^n<5nj|?$z7ne`SS?Z3w z>hi{4zW+wYua3ZCVq__voT23T;(tGOr;yn?PvTaA{vGO%q4b?5$yp3qIqH3|K9F(P zhnYjH({Dd>)G4t2V7qVCJ#zJBf^7oAT>{4!yxSz;dWZlzxOtSbrx(R{U7BICCfK1; z#Ggv%ap)`2ap_gc{IvqcxoCV*&pm>fiFoEU!Qh#Qr%z875Tf~DnPhw+MB~rU^E?4# zel(uEFBcG^@g~OnkH)uXkXj<3zeM91zo=_-BL3QQ=3b+yfTmnspnr)B0gdU4jD7r` zICKx%2t6@P{z9v)fczz2^aj_?S-)vlg4=DPH2iH@8R@-~f7Hhp{~D#maz#kPKXp)3 zHEGNJm;Eom3vNQWG|9NPDT2O2NW*`YNs{^>`WwvVe`;d;vP)OS0D{v)k;{&+(WT%M zc-`sm@VDb9`YnNR%++~??%~;$0@A^M(*%So1;o*xt`ZPnTH*-krto5v-^mM}O3t4c zOPU3QXnNY8@{CW!>v1qd(-X<~gid}k4+_l7C=;>?8W5%kTpaR}K)-NhcRae(#!b|9 znSiidKsw5Gv4G&{gZ#fVh%x&FNQaJng@C^9XoehOeo5#MIJ~a?7 z^<(z_(A`{Q@Z}b-t)U(>;7r`tjDSY zd1M76Ip7I+?Q{WQvVb^v=}Z9uX-*t`+9Dv#5DVz$ieNBOngGn=2rk zFQ9a~?DX!0B}#Zw-k+iDW(p{ERNhb2Gx8g`8;v(!aFZn<+}hPn>v!toi_@yyatI&! z;-RNAb77^E)pzDs&ia8=3Fj?G{Cpgp(9-N`dsof+N53SMvp;`&^jYi44U2qU`;A%G zF#D&l)L{FdUhVpywCsfS`P7d8dM{&^qdPmF@VGEDQbP}8=`!|e;+c0w{`E#ZDquT)xFNK+p(SBIsdLkqDZO47HH!RJ{I`9uI z8ed`i<(#EULmY)deE!NC6ONE%aqCZ6^VbehnI1)dgVJUWi$^Sf3nbI7SDcSG@FaMuqt%3stZxRp(*YYFMVc}dLOY>UY<3owmjLIV8 zpNLG|z5B8K3QhMEjZAGCabw%YmyOUb^Y`Dl{iHL{+OTCtZLW)M-U_=7*3*p&q5n%3 z{i9aLKIw?PK?~fFv;3j`qIBmL7|k9oV>fX9*R6luaNoLZTfOm@?>~jYZy#$%@vxM^ zYF*xbQojCq?dP}Jq0{*B4aJTzCohcGGF)QTlnaI1jvsSLND1ytV9bT@(c{r-OA2!dGYoWuqzIzA;CDS4B>|HdUZx&+qR{-A#ukA+1KJolW?+44{V z7gp67Kl2`DeOpw9cFp`kU&?SiyWzV(W~wkq9cCvt3!n;RLsp(5=oFye5jRhOUbnws zmVh|qC|-MT3A0Z2@U#bZOS58RcJ#Cd@7E{|>3WrGbZlMu;Cq%So58Xmm*LI31>isf z{+NJppMW^{>4O3SerkF3r+E7%N8WN8!PGy_e*o-m)ZsqLU;F8qo(A?th3&5WB6zq-YtH(f?*8Tp+uLSLEG}E$*|({G)0%an*uiXWu}vzpt~ny?>x@eJ`VJY)^5}gTwi|zaOj{OU&qywtQWF z{P6K{a{jZ7U&hklwD=GG>2B26K`L`kfYMMGZ2}-*?K1r0%8UdG$8W#!GsN$5Id$8XH9@-)G7`>n=Bdhy$wX+UW8q;db zjGM_y;Z%WZBV-D)$h%sk35XacD+{Ufc)up@C#;vk(*qyJiac|Pq z(5SqZ`<+()8yOhtU+iE*hfeO;kIr|^I%>0clQmELVVkATV>xZs`WbJ#^u*rRW=Z#O z*T33=J{_u8HhR8FRATV3sAze^IL~O`CaLq4y6(Ib6(P7xVX=U?dgyPgXuBDq(U-PeJTYJ>L%TFD=&LOKYL)+?{>!*aAHoI_>bbMd z*@YTwDZxxR?m>Blx9P0>_>;E&#QxH(;MTw3EXQeCzj;gv#?yET>G+XL=>h+Hq~YlT zU;O{Bv~RK5rs1C!SPX5#3Kv&@a1$ydi$$}px75a@N9``!aO+vEXeMwSsaZn~~8Iq#9>T;V6;_7k`` zu0dze^-uxnklBokgyRInF+w6M2u{;IK=;syaHfECCkdQ(1g8;qvS6fu&?2xjjXKE0 z7Pv0=?*ApG>tJ?-{v4%WNVQKq*ZLz$L8%y#T&WzTc;^B-LbUaf@3HWQN@nV5Ev=aD zXYPOdeo`oQ@9ve2=?kAgw-9F8n6A8IbR?tbeGvUWb=?-bGhi%ZvT??n_;$;kmfU8z z-C$WU{)?!(Y!v04T4A^@SOYZcf72y2*(yI@O*~yQ4K~d$60mM~mSSgU?!l({7TxiF zn*J6DSY>3>JfU`)O~|ue={qk{jq5ux&7RmBDz^nxZ4;dgoFN)=@W3=t)U3opcZqk_{rq(J85 z>HizXav(nKXbgq(@aXfyn09dqhZ%H~;I%e&%bU2ScZo5q*s8%hwO{^*PUE~S05 z%{RUNXvXP5_yfGv(Er`a@+ODZtx!?Nuq?G&JzPQFvAf5l( z(wR?h;eSjea4IFt{DBh86I@^ursHR(njUK5|9?=H^g%)z{uZgFS%LZ^C6QFV^?#?* zzRqTxhJTt=;jB1b*EH&s)&tN{N< zB~w;<-k&dU2luAq_v`=IY+M=0KP#+If{$zbBBbN@(?76fRfB)K(mx1tg>?L0dy8aS9hcj#arJP@)EA{ubT6i6R` zyypLdW1sK%vrZz+XZ}64LHh68g@3sfrs?(foBy1oyjV^5t^eODtueT!kN+$-WCirE z)0F63fiM0IO8a%2alOQzR*Q-&XOpQb1#_p11szi@Z0x+r7mpg zEU)p>UFWQI=Jk3Ay)Lj=IR2}Je?s38$BFdDq4LT^ngl+6m5ZYm?!;4r#=tn*vs4rSY7l<@4nj&THjy*XKR7 zR$k%{6Pbrg5EF(o|Cx=G3H}R5!qSoK#shXmY!^{Iz?mG|b+$=+>6KxrirNQa>fd;?1LuoTHsc}8 z{vOWKEj33N&*6}!#vAyJ@4n%aVY$QoK^o!fTH%!qbqlH=UTXo&0u@hg*sq zMMrvlVjvsyF z>yoT-bGSfOjZG_@pp>j46Wor)X5Eh`LIIwEcTN->DIl=Ex_fup`9`ypqMEWhiACAr z+VE_MtW~-wg~PL*Og|W!6KpE6w3aDoHQ1 zMok=yuL8bjoM@2d|IiZbY7k*lLM{HscPl?1{|8QB%nJBFkP1&x=XsFz8}>{4_@B1~ zUft=r)l&aO%5t&IHl6-{{-1cMgkBcu<>f6S)KZts*HO@4q03{aZp8d7&%E}9VLY#m zs_l)kt>&TK@U*LzQ|=qVb@|pphUdPAALEOmE2+L|7{(SLX!=HvDqlYIp zf&=r=a?D;s%XnWeJqWcCl+8EJ&mAJ#R$Q}6pMQAy{|Ed3SV8cee=Sg2{M8BR_`UZ3 zHL-1Mp}-ga2bFd}KuE{$<^Lbx1vkOun*RSDy4Evq2s&|y`d}^o4Q>&DPbv6)D5Cxp&NFs24-svRe5+k2$6y!T_+e&=r62J$ z)Wu`Io?dhL_;>F)PYk^qnug|N_o3o8d5HMA7FiLcYy9YZ-_1Go zr+6OO@r-P5HGkKu>b)yb>XrY1L%9!#G(sNaq1pIh#-CX>khsR4oSnOc*7{R94~@qS zGaCEaKGGc9>)-S9`7_3}r>g5%Bdy^M_ulZLKdyiRD^R53br3DD-_4ixd1yX7{Wc7*(py4T^+rgJeCs)^)ea|{MbxSh zI%Y=c7JOYJ+>?>M+aS4H!1+PrlUj|ZsoU1LPQPP~r5Yb-^V_HwHokB5@M%wOaWmg5 z^Q%|ft%!QDd3~$(vdk7NSqfY=&LYN7*pH@i@tmi_d-vq`F!mn356va|q2fkJ?tJp6 z;&)!;%Gy%*c}Y~dl((5Ck8g@fp89ZJ{<+-fA<{8?=f{3;h^n%IfNega?n=l?1#y9Ej9`2F^ORBQkIx$xc_V9&zu<^NPTPkCWa^{xNsmDcUQ zNUy)n)5!?V{_bdykvw?)1^xHg|H7xwvI6)oQX)?J^sWD=mDUG82UBMS;Sc=JE~x_l zKP&BWn{gWbXZZ1dQ15E!|106X)8bzqI3#bDTG=P_!4B;QTc+`jFPEF1uD*w>#s^U&q};$(7yB2I<&`ad&E|cEUQMtbf*!yHRfaW z`)ahT(AMvAXjTsU&QHTYz#57>XZ@w3ir-2P%YE>DsQHepvQ3h%U*;sVYO$MTuzly3 z^+*D3Q(JauOI3VZRoJ?tyj$1EGB>YdeDXQJEGh?`SBL9w`_3QZyOJ1?+GR;@mo_y; z|EH+cDx2?y`uwpp{bPFYRcA3mN|eC9tbe(OI?^m9J_ z=3DZ=6k7;R642 zLM~^@`PRRvwAb4F_VoFK+5RDwWu?&&`D820`FrR0=fbT7Zqz(YEwlH0KhB)lTiwR) zLg7r+aYNk~8qHEo>85>iR%&>fX||7R+#kxd3^H!Ge{UL(fg9@JZ&bTGyE*B&9{#vt z-*9u4ajMQ2LG#4gl9@r);!$jp>zeCTq2lCf!R9mZ=ahxW6<6`*8 zf73$Q8#&6Y1tn`%OKUqTz5fAcNvwOSm6PLN`Eq6JY?a3GaQv&Z{~?L77Wzk9KKX5o z&Oj6D3Aoi+l*{AXla67=ZXIr7PL|N{M|L~->an%vU#Xqlj3Aut7)>{cryi}lUJ}`S zcOTG2CO6w^}y!l6p>ei3yk3ZUjv%fi6 z9{--41C`qxldqH;r6ptW#eZd!bmyV@{8#xh=aDmidG;gI+kCmL_I6~J)Tz1C7R{Bq iWwT1RYN5-n*ZeE$+vM-{w6Fh{&QrHlF;A_%|NlRj + +#include "dbgcmd.h" +#include "dbgexcept.h" + +/////////////////////////////////////////////////////////////////////////////// + +// класс для перехвата вывода в отладчик + +class OutputReader : public IDebugOutputCallbacks { + +public: + + OutputReader( IDebugClient *debugClient ) + { + HRESULT hres; + + try { + + m_debugClient = debugClient; + m_debugClient->AddRef(); + + hres = m_debugClient->GetOutputCallbacks( &m_previousCallback ); + if ( FAILED( hres ) ) + { + throw hres; + } + + hres = m_debugClient->SetOutputCallbacks( this ); + if ( FAILED( hres ) ) + { + throw hres; + } + + } catch( ... ) + { + m_debugClient->Release(); + m_debugClient = NULL; + } + } + + ~OutputReader() + { + if ( m_debugClient ) + { + m_debugClient->SetOutputCallbacks( m_previousCallback ); + m_debugClient->Release(); + } + } + + const std::string& + Line() const { + return m_readLine; + } + +private: + + // IUnknown. + STDMETHOD(QueryInterface)( + __in REFIID InterfaceId, + __out PVOID* Interface ) { + return E_NOINTERFACE; + } + + STDMETHOD_(ULONG, AddRef)() { + return 1L; + } + + + STDMETHOD_(ULONG, Release)() { + return 0L; + } + + STDMETHOD(Output)( + __in ULONG Mask, + __in PCSTR Text ) + { + if ( Mask == DEBUG_OUTPUT_NORMAL ) + { + m_readLine += std::string( Text ); + } + + return S_OK; + } + +private: + + std::string m_readLine; + + IDebugClient *m_debugClient; + + IDebugOutputCallbacks *m_previousCallback; +}; + + +/////////////////////////////////////////////////////////////////////////////// + +std::string +dbgCommand( const std::string &command ) +{ + HRESULT hres; + + try { + + OutputReader outReader( g_Ext->m_Client ); + + hres = g_Ext->m_Control->Execute( DEBUG_OUTCTL_THIS_CLIENT, command.c_str(), 0 ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::Execute failed" ); + + return std::string( outReader.Line() ); + } + catch( std::exception &e ) + { + g_Ext->Out( "pykd error: %s\n", e.what() ); + } + catch(...) + { + g_Ext->Out( "pykd unexpected error\n" ); + } + + return "error"; +} + +/////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/dbgcmd.h b/pykd/dbgcmd.h new file mode 100644 index 0000000..b34637f --- /dev/null +++ b/pykd/dbgcmd.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include +#include + +///////////////////////////////////////////////////////////////////////////////// + +std::string +dbgCommand( const std::string &command ); + + + +///////////////////////////////////////////////////////////////////////////////// + diff --git a/pykd/dbgexcept.h b/pykd/dbgexcept.h new file mode 100644 index 0000000..83a7701 --- /dev/null +++ b/pykd/dbgexcept.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +///////////////////////////////////////////////////////////////////////////////// + +class DbgException : public std::exception +{ +public: + + DbgException( const char* desc ) : + std::exception( desc ) + {} +}; + +///////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp new file mode 100644 index 0000000..dd3133b --- /dev/null +++ b/pykd/dbgext.cpp @@ -0,0 +1,143 @@ +#include "stdafx.h" + +#include + +#include +#include +#include +#include + +#include "dbgprint.h" +#include "dbgreg.h" +#include "dbgtype.h" +#include "dbgmodule.h" +#include "dbgsym.h" +#include "dbgmem.h" +#include "dbgsystem.h" +#include "dbgcmd.h" + +///////////////////////////////////////////////////////////////////////////////// + +BOOST_PYTHON_MODULE( pykd ) +{ + boost::python::def( "dprint", &DbgPrint::dprint ); + boost::python::def( "dprintln", &DbgPrint::dprintln ); + boost::python::def( "dbgCommand", &dbgCommand ); + boost::python::def( "is64bitSystem", is64bitSystem ); + boost::python::def( "reg", &loadRegister ); + boost::python::def( "typedVar", &loadTypedVar ); + boost::python::def( "containingRecord", &containingRecord ); + boost::python::def( "loadModule", &loadModule ); + boost::python::def( "findSymbol", &findSymbolForAddress ); + boost::python::def( "getOffset", &findAddressForSymbol ); + boost::python::def( "findModule", &findModule ); + boost::python::def( "addr64", &addr64 ); + boost::python::def( "compareMemory", &compareMemory ); + boost::python::class_( "typedVarClass" ) + .def("getAddress", &typedVarClass::getAddress ); + boost::python::class_( "dbgModuleClass" ) + .add_property("begin", &dbgModuleClass::getBegin ) + .add_property("end", &dbgModuleClass::getEnd ) + .def("contain", &dbgModuleClass::contain ); +} + +///////////////////////////////////////////////////////////////////////////////// + +class EXT_CLASS : public ExtExtension +{ +public: + + virtual HRESULT Initialize(void) { + + HRESULT hr = ExtExtension::Initialize(); + if ( FAILED( hr ) ) + return hr; + + Py_Initialize(); + + PyImport_AppendInittab("pykd",initpykd ); + + return hr; + } + + virtual void Uninitialize(void) { + + Py_Finalize(); + } + + +public: + EXT_COMMAND_METHOD( info ); + EXT_COMMAND_METHOD( exec ); +}; + +EXT_DECLARE_GLOBALS(); + +///////////////////////////////////////////////////////////////////////////////// + +EXT_COMMAND( + info, + "Python Info", + "" ) +{ + Out( "Python Info" ); +} + +///////////////////////////////////////////////////////////////////////////////// + +EXT_COMMAND( + exec, + "Execute python code", + "{f;b;;quite mode}{;x}" ) +{ + bool fromFile = false; + + if ( HasArg( "f" ) ) + fromFile = true; + + try { + + + boost::python::object main = boost::python::import("__main__"); + + boost::python::object global(main.attr("__dict__")); + + boost::python::object result; + + if ( fromFile ) + { + result = boost::python::exec_file( GetUnnamedArgStr( 0 ), global, global ); + } + else + { + result = boost::python::exec( GetUnnamedArgStr( 0 ), global, global ); + } + } + catch( boost::python::error_already_set const & ) + { + // ошибка в скрипте + PyObject *errtype = NULL, *errvalue = NULL, *traceback = NULL; + + PyErr_Fetch( &errtype, &errvalue, &traceback ); + + if(errvalue != NULL) + { + PyObject *s = PyObject_Str(errvalue); + + DbgPrint::dprintln( PyString_AS_STRING( s ) ); + + Py_DECREF(s); + } + + Py_XDECREF(errvalue); + Py_XDECREF(errtype); + Py_XDECREF(traceback); + } + catch(...) + { + } + + + } + +///////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/dbgmem.cpp b/pykd/dbgmem.cpp new file mode 100644 index 0000000..3eb3547 --- /dev/null +++ b/pykd/dbgmem.cpp @@ -0,0 +1,92 @@ +#include "stdafx.h" + +#include + +#include "dbgexcept.h" +#include "dbgmem.h" + +using namespace std; + +/////////////////////////////////////////////////////////////////////////////////// + +bool +loadMemory( ULONG64 address, PVOID dest, ULONG length ) +{ + address = addr64( address ); + + try { + + HRESULT hres = g_Ext->m_Data->ReadVirtual( address, dest, length, NULL ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugDataSpace::ReadVirtual failed" ); + + return true; + + } + catch( std::exception &e ) + { + g_Ext->Out( "pykd error: %s\n", e.what() ); + } + catch(...) + { + g_Ext->Out( "Kd2Lua unexpected error\n" ); + } + + return false; +} + +/////////////////////////////////////////////////////////////////////////////////// + +ULONG64 +addr64( ULONG64 addr ) +{ + if ( *( (ULONG*)&addr + 1 ) == 0 ) + *( (ULONG*)&addr + 1 ) = 0xFFFFFFFF; + + return addr; +} + +/////////////////////////////////////////////////////////////////////////////////// + +bool +compareMemory( ULONG64 addr1, ULONG64 addr2, ULONG length ) +{ + HRESULT hres; + bool result = false; + + addr1 = addr64( addr1 ); + addr2 = addr64( addr2 ); + + char* m1 = new char[length]; + char* m2 = new char[length]; + + try { + + hres = g_Ext->m_Data->ReadVirtual( addr1, m1, length, NULL ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugDataSpace::ReadVirtual failed" ); + + hres = g_Ext->m_Data->ReadVirtual( addr2, m2, length, NULL ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugDataSpace::ReadVirtual failed" ); + + result = memcmp( m1, m2, length ) == 0; + + } + catch( std::exception &e ) + { + g_Ext->Out( "pykd error: %s\n", e.what() ); + } + catch(...) + { + g_Ext->Out( "Kd2Lua unexpected error\n" ); + } + + delete[] m1; + delete[] m2; + + return result; +} + +/////////////////////////////////////////////////////////////////////////////////// + diff --git a/pykd/dbgmem.h b/pykd/dbgmem.h new file mode 100644 index 0000000..be5b270 --- /dev/null +++ b/pykd/dbgmem.h @@ -0,0 +1,14 @@ +#pragma once + +///////////////////////////////////////////////////////////////////////////////// + +bool +loadMemory( ULONG64 address, PVOID dest, ULONG length ); + +bool +compareMemory( ULONG64 addr1, ULONG64 addr2, ULONG length ); + +ULONG64 +addr64( ULONG64 addr ); + +///////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/dbgmodule.cpp b/pykd/dbgmodule.cpp new file mode 100644 index 0000000..722157e --- /dev/null +++ b/pykd/dbgmodule.cpp @@ -0,0 +1,84 @@ +#include "stdafx.h" + +#include + +#include "dbgmodule.h" +#include "dbgexcept.h" +#include "dbgmem.h" + +///////////////////////////////////////////////////////////////////////////////// + +boost::python::object +loadModule( const std::string &moduleName ) +{ + HRESULT hres; + + try { + ULONG64 moduleBase; + hres = g_Ext->m_Symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetModuleByModuleName failed" ); + + DEBUG_MODULE_PARAMETERS moduleParam = { 0 }; + hres = g_Ext->m_Symbols->GetModuleParameters( 1, &moduleBase, 0, &moduleParam ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetModuleParameters failed" ); + + + return boost::python::object( dbgModuleClass( moduleBase, moduleParam.Size ) ); + + } + catch( std::exception &e ) + { + g_Ext->Out( "pykd error: %s\n", e.what() ); + } + catch(...) + { + g_Ext->Out( "pykd unexpected error\n" ); + } + + return boost::python::object(); +} + +///////////////////////////////////////////////////////////////////////////////// + +boost::python::object +findModule( ULONG64 addr ) +{ + HRESULT hres; + + addr = addr64( addr ); + + try { + + ULONG moduleIndex; + ULONG64 moduleBase; + hres = g_Ext->m_Symbols->GetModuleByOffset( addr, 0, &moduleIndex, &moduleBase ); + + if ( FAILED( hres ) ) + { + return boost::python::object(); + } + + DEBUG_MODULE_PARAMETERS moduleParam = { 0 }; + hres = g_Ext->m_Symbols->GetModuleParameters( 1, &moduleBase, 0, &moduleParam ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetModuleParameters failed" ); + + + return boost::python::object( dbgModuleClass( moduleBase, moduleParam.Size ) ); + + } + catch( std::exception &e ) + { + g_Ext->Out( "pykd error: %s\n", e.what() ); + } + catch(...) + { + g_Ext->Out( "pykd unexpected error\n" ); + } + + return boost::python::object(); +} + +///////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgmodule.h b/pykd/dbgmodule.h new file mode 100644 index 0000000..8711dcd --- /dev/null +++ b/pykd/dbgmodule.h @@ -0,0 +1,58 @@ +#pragma once + +#include + +#include +#include + +///////////////////////////////////////////////////////////////////////////////// + +class dbgModuleClass { + +public: + + dbgModuleClass() : + m_base( 0 ), + m_end( 0 ) + {} + + dbgModuleClass( ULONG64 base, ULONG size ) : + m_base( base ), + m_end( base + size ) + {} + + ULONG64 + getBegin() const { + return m_base; + } + + ULONG64 + getEnd() const { + return m_end; + } + + bool + contain( ULONG64 addr ) const { + if ( *( (ULONG*)&addr + 1 ) == 0 ) + *( (ULONG*)&addr + 1 ) = 0xFFFFFFFF; + + return m_base <= addr && addr <= m_end; + } + + +private: + + ULONG64 m_base; + ULONG64 m_end; +}; + +///////////////////////////////////////////////////////////////////////////////// + +boost::python::object +loadModule( const std::string &moduleName ); + + +boost::python::object +findModule( ULONG64 addr ); + +///////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/dbgprint.cpp b/pykd/dbgprint.cpp new file mode 100644 index 0000000..d7c9a98 --- /dev/null +++ b/pykd/dbgprint.cpp @@ -0,0 +1,16 @@ +#include "stdafx.h" +#include "dbgprint.h" +#include + +using namespace std; + +void DbgPrint::dprint( const string& str ) +{ + g_Ext->Out( str.c_str() ); +} + +void DbgPrint::dprintln( const std::string& str ) +{ + g_Ext->Out( str.c_str() ); + g_Ext->Out( "\r\n" ); +} \ No newline at end of file diff --git a/pykd/dbgprint.h b/pykd/dbgprint.h new file mode 100644 index 0000000..d3b0f6e --- /dev/null +++ b/pykd/dbgprint.h @@ -0,0 +1,15 @@ +// вывод информации в отладчик + +#pragma once + +#include + +class DbgPrint { + +public: + + static void dprint( const std::string& str ); + + static void dprintln( const std::string& str ); +}; + diff --git a/pykd/dbgreg.cpp b/pykd/dbgreg.cpp new file mode 100644 index 0000000..ee48e00 --- /dev/null +++ b/pykd/dbgreg.cpp @@ -0,0 +1,62 @@ +#include "stdafx.h" + +#include + +#include "dbgreg.h" +#include "dbgexcept.h" + +using namespace std; + +/////////////////////////////////////////////////////////////////////////////////// + +boost::python::object +loadRegister( const std::string ®isterName ) +{ + HRESULT hres; + + + try { + + ULONG registerIndex = 0; + + hres = g_Ext->m_Registers->GetIndexByName( registerName.c_str(), ®isterIndex ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugRegister::GetIndexByName failed" ); + + DEBUG_VALUE debugValue; + hres = g_Ext->m_Registers->GetValue( registerIndex, &debugValue ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugRegister::GetValue failed" ); + + switch( debugValue.Type ) + { + case DEBUG_VALUE_INT8: + return boost::python::long_( debugValue.I8 ); + break; + + case DEBUG_VALUE_INT16: + return boost::python::long_( debugValue.I16 ); + break; + + case DEBUG_VALUE_INT32: + return boost::python::long_( debugValue.I32 ); + break; + + case DEBUG_VALUE_INT64: + return boost::python::long_(debugValue.I64 ); + break; + } + } + catch( std::exception &e ) + { + g_Ext->Out( "pykd error: %s\n", e.what() ); + } + catch(...) + { + g_Ext->Out( "pykd unexpected error\n" ); + } + + return boost::python::str( "REG_ERR" ); +} + +/////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgreg.h b/pykd/dbgreg.h new file mode 100644 index 0000000..b43ef27 --- /dev/null +++ b/pykd/dbgreg.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#include +#include + +///////////////////////////////////////////////////////////////////////////////// + +boost::python::object +loadRegister( const std::string ®isterName ); + +///////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/dbgsym.cpp b/pykd/dbgsym.cpp new file mode 100644 index 0000000..9d63ad9 --- /dev/null +++ b/pykd/dbgsym.cpp @@ -0,0 +1,105 @@ +#include "stdafx.h" + +#include + +#include "dbgsym.h" +#include "dbgexcept.h" + +///////////////////////////////////////////////////////////////////////////////// + +boost::python::object +findSymbolForAddress( ULONG64 addr ) +{ + HRESULT hres; + + try { + + DEBUG_MODULE_AND_ID debugId; + ULONG64 displace = 0; + + if ( *( (ULONG*)&addr + 1 ) == 0 ) + *( (ULONG*)&addr + 1 ) = 0xFFFFFFFF; + + ULONG moduleIndex; + ULONG64 moduleBase; + hres = g_Ext->m_Symbols->GetModuleByOffset( addr, 0, &moduleIndex, &moduleBase ); + + if ( FAILED( hres ) ) + { + return boost::python::object( "out of module" ); + } + + char moduleName[0x100]; + hres = g_Ext->m_Symbols2->GetModuleNameString( DEBUG_MODNAME_MODULE, moduleIndex, moduleBase, + moduleName, sizeof( moduleName ), NULL ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol2::GetModuleNameString failed" ); + + ULONG entries = 0; + hres = g_Ext->m_Symbols3->GetSymbolEntriesByOffset( addr, 0, &debugId, &displace, 1, &entries ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol3::GetSymbolEntriesByOffset failed" ); + + std::stringstream ss; + + if ( entries == 0 ) + { + ss << moduleName << "+" << std::hex << ( addr - moduleBase ); + return boost::python::object( ss.str() ); + } + + char symbolName[0x100]; + hres = g_Ext->m_Symbols3->GetSymbolEntryString( &debugId, 0, symbolName, sizeof(symbolName ), NULL ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol3::GetSymbolEntryString failed" ); + + ss << moduleName << "!" << symbolName; + return boost::python::object( ss.str() ); + + } + catch( std::exception &e ) + { + g_Ext->Out( "pykd error: %s\n", e.what() ); + } + catch(...) + { + g_Ext->Out( "pykd unexpected error\n" ); + } + + return boost::python::object( addr ); +} + +///////////////////////////////////////////////////////////////////////////////// + +ULONG64 +findAddressForSymbol( const std::string &moduleName, const std::string &symbolName ) +{ + HRESULT hres; + + try { + + std::string ModuleSymName = moduleName; + ModuleSymName += "!"; + ModuleSymName += symbolName; + + ULONG64 offset = 0ULL; + hres = g_Ext->m_Symbols->GetOffsetByName( ModuleSymName.c_str(), &offset ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetOffsetByName failed" ); + + return offset; + } + catch( std::exception &e ) + { + g_Ext->Out( "pykd error: %s\n", e.what() ); + } + catch(...) + { + g_Ext->Out( "pykd unexpected error\n" ); + } + + return (ULONG64)~0; +} + +///////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/dbgsym.h b/pykd/dbgsym.h new file mode 100644 index 0000000..864d441 --- /dev/null +++ b/pykd/dbgsym.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include +#include + +///////////////////////////////////////////////////////////////////////////////// + +boost::python::object +findSymbolForAddress( ULONG64 addr ); + +ULONG64 +findAddressForSymbol( const std::string &moduleName, const std::string &symbolName ); + +///////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgsystem.cpp b/pykd/dbgsystem.cpp new file mode 100644 index 0000000..d51f058 --- /dev/null +++ b/pykd/dbgsystem.cpp @@ -0,0 +1,33 @@ +#include "stdafx.h" + +#include +#include + +#include "dbgsystem.h" + +///////////////////////////////////////////////////////////////////////////////// + +bool +is64bitSystem() +{ + HRESULT hres; + + try { + hres = g_Ext->m_Control->IsPointer64Bit(); + + return hres == S_OK; + + } + catch( std::exception &e ) + { + g_Ext->Out( "pykd error: %s\n", e.what() ); + } + catch(...) + { + g_Ext->Out( "pykd unexpected error\n" ); + } + + return false; +} + +///////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgsystem.h b/pykd/dbgsystem.h new file mode 100644 index 0000000..7342852 --- /dev/null +++ b/pykd/dbgsystem.h @@ -0,0 +1,14 @@ +#pragma once + +///////////////////////////////////////////////////////////////////////////////// + +bool +is64bitSystem(); + +inline +int +ptrSize() { + return is64bitSystem() ? 8 : 4; +} + +///////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/dbgtype.cpp b/pykd/dbgtype.cpp new file mode 100644 index 0000000..ebdf3e4 --- /dev/null +++ b/pykd/dbgtype.cpp @@ -0,0 +1,266 @@ +#include "stdafx.h" + +#include + +#include "dbgtype.h" +#include "dbgexcept.h" +#include "dbgmem.h" +#include "dbgsystem.h" + +using namespace std; + +bool +isBaseType( const std::string &typeName ); + +boost::python::object +loadBaseType( const std::string &typeName, ULONG64 address, ULONG size ); + +typedef +boost::python::object +(*basicTypeLoader)( ULONG64 address, ULONG size ); + +boost::python::object +voidLoader( ULONG64 address, ULONG size ) { + return boost::python::object(); +} + +template< typename valType> +boost::python::object +valueLoader( ULONG64 address, ULONG size ); + +template<> +boost::python::object +valueLoader( ULONG64 address, ULONG size ) +{ + if ( is64bitSystem() ) + return valueLoader<__int64>( address, size ); + else + return valueLoader( address, size ); +} + +static const char* +basicTypeNames[] = { + "unsigned char", + "char", + "unsigned short", + "short", + "unsigned long", + "long", + "", + "void" +}; + +basicTypeLoader basicTypeLoaders[] = { + valueLoader, + valueLoader, + valueLoader, + valueLoader, + valueLoader, + valueLoader, + valueLoader, + voidLoader }; + +/////////////////////////////////////////////////////////////////////////////////// +// +boost::python::object +loadTypedVar( const std::string &moduleName, const std::string &typeName, ULONG64 address ) +{ + HRESULT hres; + + try { + + ULONG64 moduleBase; + + if ( typeName.find("*") < typeName.size() ) + { + return valueLoader( address, ptrSize() ); + } + + hres = g_Ext->m_Symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetModuleByModuleName failed" ); + + ULONG typeId; + hres = g_Ext->m_Symbols->GetTypeId( moduleBase, typeName.c_str(), &typeId ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetTypeId failed" ); + + typedVarClass temp( address ); + boost::python::object var( temp ); + + for ( ULONG i = 0; ; ++i ) + { + char fieldName[100]; + hres = g_Ext->m_Symbols2->GetFieldName( moduleBase, typeId, i, fieldName, sizeof(fieldName), NULL ); + + if ( FAILED( hres ) ) + break; + + ULONG fieldTypeId; + ULONG fieldOffset; + hres = g_Ext->m_Symbols3->GetFieldTypeAndOffset( moduleBase, typeId, fieldName, &fieldTypeId, &fieldOffset ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol3::GetFieldTypeAndOffset failed" ); + + char fieldTypeName[100]; + hres = g_Ext->m_Symbols->GetTypeName( moduleBase, fieldTypeId, fieldTypeName, sizeof(fieldTypeName), NULL ); + + ULONG fieldSize; + hres = g_Ext->m_Symbols->GetTypeSize( moduleBase, fieldTypeId, &fieldSize ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetTypeName failed" ); + + if ( isBaseType( fieldTypeName ) ) + { + var.attr( fieldName ) = loadBaseType( fieldTypeName, address + fieldOffset, fieldSize ); + } + else + { + var.attr( fieldName ) = loadTypedVar( moduleName, fieldTypeName, address + fieldOffset ); + } + } + + return var; + } + + catch( std::exception &e ) + { + g_Ext->Out( "pykd error: %s\n", e.what() ); + } + catch(...) + { + g_Ext->Out( "pykd unexpected error\n" ); + } + + return boost::python::str( "VAR_ERR" ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +boost::python::object +containingRecord( ULONG64 address, const std::string &moduleName, const std::string &typeName, const std::string &fieldName ) +{ + HRESULT hres; + + try { + + ULONG64 moduleBase; + + hres = g_Ext->m_Symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetModuleByModuleName failed" ); + + ULONG typeId; + hres = g_Ext->m_Symbols->GetTypeId( moduleBase, typeName.c_str(), &typeId ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetTypeId failed" ); + + ULONG fieldTypeId; + ULONG fieldOffset; + hres = g_Ext->m_Symbols3->GetFieldTypeAndOffset( moduleBase, typeId, fieldName.c_str(), &fieldTypeId, &fieldOffset ); + + return loadTypedVar( moduleName, typeName, address - fieldOffset ); + } + + catch( std::exception &e ) + { + g_Ext->Out( "pykd error: %s\n", e.what() ); + } + catch(...) + { + g_Ext->Out( "pykd unexpected error\n" ); + } + + return boost::python::str( "VAR_ERR" ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +bool +isBaseType( const std::string &typeName ) +{ + for ( int i = 0; i < sizeof( basicTypeNames ) / sizeof( char* ); ++i ) + { + if ( typeName == basicTypeNames[i] ) + return true; + + if ( typeName == ( std::string( basicTypeNames[i] ) + "*" ) ) + return true; + + if ( typeName == ( std::string( basicTypeNames[i] ) + "[]" ) ) + return true; + + if ( typeName == ( std::string( basicTypeNames[i] ) + "*[]" ) ) + return true; + } + + return false; +} + +/////////////////////////////////////////////////////////////////////////////////// + +boost::python::object +loadBaseType( const std::string &typeName, ULONG64 address, ULONG size ) +{ + for ( int i = 0; i < sizeof( basicTypeNames ) / sizeof( char* ); ++i ) + { + if ( typeName == basicTypeNames[i] ) + return basicTypeLoaders[i]( address, size ); + + if ( typeName == ( std::string( basicTypeNames[i] ) + "*" ) ) + return valueLoader( address, size ); + + if ( typeName == ( std::string( basicTypeNames[i] ) + "[]" ) ) + return basicTypeLoaders[i]( address, size ); + + if ( typeName == ( std::string( basicTypeNames[i] ) + "*[]" ) ) + return valueLoader( address, size ); + } + + return boost::python::object(); +} + +/////////////////////////////////////////////////////////////////////////////////// + + + +template< typename valType> +boost::python::object +valueLoader( ULONG64 address, ULONG size ) +{ + if ( size == sizeof(valType) ) + { + valType v; + if ( loadMemory( address, &v, sizeof(v) ) ) + return boost::python::long_( (unsigned __int64)v ); + } + else + { + boost::python::dict arr; + + for ( int i = 0; i < size / sizeof(valType); ++i ) + { + valType v; + if ( !loadMemory( address + i * sizeof(valType), &v, sizeof(v) ) ) + return boost::python::object(); + + arr[i] = boost::python::long_( (unsigned __int64)v ); + } + + return arr; + } + + return boost::python::object(); +} + +/////////////////////////////////////////////////////////////////////////////////// + +boost::python::object +loadComplexType( const std::string &typeName, ULONG64 address, ULONG size ) +{ + return boost::python::object(); +} + +/////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/dbgtype.h b/pykd/dbgtype.h new file mode 100644 index 0000000..631e1ab --- /dev/null +++ b/pykd/dbgtype.h @@ -0,0 +1,41 @@ +#pragma once + +#include + +#include +#include + +///////////////////////////////////////////////////////////////////////////////// + +class typedVarClass { + +public: + + typedVarClass() + {} + + typedVarClass( ULONG64 addr ) : + m_addr( addr ) + {} + + ULONG64 + getAddress() const { + return m_addr; + } + +private: + + ULONG64 m_addr; + +}; + +///////////////////////////////////////////////////////////////////////////////// + +boost::python::object +loadTypedVar( const std::string &moduleName, const std::string &typeName, ULONG64 address ); + +boost::python::object +containingRecord( ULONG64 address, const std::string &moduleName, const std::string &typeName, const std::string &fieldName ); + + +///////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/pykd.cpp b/pykd/pykd.cpp new file mode 100644 index 0000000..e69de29 diff --git a/pykd/pykd.def b/pykd/pykd.def new file mode 100644 index 0000000..38ab092 --- /dev/null +++ b/pykd/pykd.def @@ -0,0 +1,6 @@ +EXPORTS + DebugExtensionInitialize + DebugExtensionUninitialize + + info + exec \ No newline at end of file diff --git a/pykd/pykd.suo b/pykd/pykd.suo new file mode 100644 index 0000000000000000000000000000000000000000..21746f0643995db1fef5daf2f717f4b128840bfa GIT binary patch literal 7680 zcmeHMO-x)>6g~seg4JRRqGGKhKbE#Inc+_;smcJACJ<_A!37%_W+-$RCd^R8LZWVT zW8%)lXrf77s0pSU<5JleO$^3`3s+@fbW__zO1i5((WYg62N`hb(Xp zvfgK{VF_xk_d%3Wlroejw_6RX`#8N;rH?0AGqO$+*Pi zstm|9>bP9SH3*qZe=N&{byDQ2#2Cg6<;XHzJtk%{zDT{`HX#c#g&+BjLY}w;Nfb8<$JU^(wc7QlpGG-h-JiBqjki?6`6Inmu7?h^SEW1$e@`}CI{IU{2dwa|pEB}Db4>NBl$e6nFyx_8p`ah_LD zv>Y1MrXbC@%)-yl0bRl>qTSK}gzJ!YISJVY(H~GU$AEnyg~KBXi5Bo?7;g@vZvlEt za_8FTj{jV%-SC$y6@k5n!Fxg3HkeT#@OLq9V$S4Le~xb_ z2!m4fPx4=a=S)C~upYR}H6Q(nrDnSPypMZS81jXb?-?I7_xbwbUdo~+%s(#nLKb>b z0Cr;h233q2t8cF@SJ>8BNZ+=JvfQNl-ykHNh1W3;9JOL$P8N5K!p1z}?=WP#WXZ*N zkAvqtY(>ONBBjX;gRo&7m`5z&$nA)92Jy%Igt14;qON*u_y1nZ8^8+9S~J^qzJO;j z*dP-UdBIkL|nR^a#;{s*kZ*tLISSF5=jy#tAxeGhhzY1fSi;)h9i;_&Ln+ge) zyjBczCK8b%as7CkCqA6rs}sHL7)gm+(BkuE{CZHjRci%C@HMxzwzV4zIj&)U zy#jc{oFl&bwDstn&EFjPGV||2_-|NwDYJ!f#1eCc=+@avuRaY6jMxR>&L;MD&f!PprK;D)fr%|HX@N~tkE0$0gKHQ>)P z2QkGd|EDnab!*}tXwMU140+WwFko?q6xP69DxUus&pZP;5)JiA z67Mn-`7=ssPN)3qF!mM-snAgM06G>eX^r0vL6bPU(b^N z^+mT}`*Cu5Ot+cXwq?)-m8e6F6;sXZAmd@sxqY zedGB8lBqf%-F6LP@YE5cOI{>T9(7fWcDcN?PCUw=qS$L}|4QXNQ6ai(-Un-b-5^`8 zf}MEEXCL=Ieo^IDP<|y~A8Vaki!g&T + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pykd/stdafx.cpp b/pykd/stdafx.cpp new file mode 100644 index 0000000..b1373b9 --- /dev/null +++ b/pykd/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// pykd.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/pykd/stdafx.h b/pykd/stdafx.h new file mode 100644 index 0000000..b1739cf --- /dev/null +++ b/pykd/stdafx.h @@ -0,0 +1,35 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Allow use of features specific to Windows XP or later. +#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. +#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later. +#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE. +#endif + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files: +#include + +#define __field_ecount_opt(x) + + +#define BOOST_PYTHON_STATIC_LIB + +// TODO: reference additional headers your program requires here diff --git a/test/print.py b/test/print.py new file mode 100644 index 0000000..e2b4b4f --- /dev/null +++ b/test/print.py @@ -0,0 +1,8 @@ +from pykd import * + +dprint ( "hello windbg!\n" ) +dprintln ( "hello windbg!" ) +hello = "hello windbg!" +dprintln( hello ) +dprintln( hello + " from python" ) + diff --git a/test/regs.py b/test/regs.py new file mode 100644 index 0000000..f990d79 --- /dev/null +++ b/test/regs.py @@ -0,0 +1,16 @@ +from pykd import * + + +dprintln( "regs tests begin" ) + +al = reg("al") +ax = reg("ax") +eax = reg("eax") + + +dprintln( "al: " + str(al) ) +dprintln( "ax: " + str(ax) ) +dprintln( "eax: " + str(eax) ) + + +dprintln( "regs tests end" ) \ No newline at end of file diff --git a/test/type.py b/test/type.py new file mode 100644 index 0000000..04390ec --- /dev/null +++ b/test/type.py @@ -0,0 +1,13 @@ +from pykd import * + +dprintln( "type test begin" ) + +idtr=reg("idtr") + +var = typedVar( "nt", "_KIDTENTRY", idtr ) + +for t, v in var.iteritems(): + dprintln( t + " : " + str(v) ) + + +dprintln( "type test end" ) \ No newline at end of file