From e2a95f68380048396f9983efd401049666f70a93 Mon Sep 17 00:00:00 2001 From: de4dot Date: Sat, 23 Nov 2013 22:00:13 +0100 Subject: [PATCH] Support Agile.NET 6.3.0.10 --- de4dot.code/de4dot.code.csproj | 4 +- .../deobfuscators/Agile_NET/vm/v2/CSVM1.bin | Bin 0 -> 9154 bytes .../Agile_NET/vm/v2/CSVM1_v2.bin | Bin 9520 -> 0 bytes .../deobfuscators/Agile_NET/vm/v2/CSVM2.bin | Bin 0 -> 9138 bytes .../Agile_NET/vm/v2/CSVM2_v2.bin | Bin 9520 -> 0 bytes .../deobfuscators/Agile_NET/vm/v2/CSVM3.bin | Bin 0 -> 9186 bytes .../Agile_NET/vm/v2/CSVM3_v2.bin | Bin 9580 -> 0 bytes .../deobfuscators/Agile_NET/vm/v2/CSVM4.bin | Bin 0 -> 9328 bytes .../vm/v2/CompositeHandlerDetector.cs | 241 ++---- .../Agile_NET/vm/v2/CompositeOpCodeHandler.cs | 40 +- .../deobfuscators/Agile_NET/vm/v2/CsvmInfo.cs | 90 ++- .../Agile_NET/vm/v2/CsvmResources.Designer.cs | 22 +- .../Agile_NET/vm/v2/CsvmResources.resx | 17 +- .../vm/v2/CsvmToCilMethodConverter.cs | 7 +- .../Agile_NET/vm/v2/MethodFinder.cs | 109 --- .../Agile_NET/vm/v2/MethodSigInfoCreator.cs | 737 ------------------ .../Agile_NET/vm/v2/OpCodeHandler.cs | 38 - .../Agile_NET/vm/v2/OpCodeHandlerInfo.cs | 19 +- .../Agile_NET/vm/v2/OpCodeHandlerInfos.cs | 80 +- .../Agile_NET/vm/v2/SigCreator.cs | 593 ++++++++++++++ .../deobfuscators/Agile_NET/vm/v2/VmOpCode.cs | 18 +- .../vm/v2/VmOpCodeHandlerDetector.cs | 60 +- de4dot.mdecrypt/DynamicMethodsDecrypter.cs | 56 ++ 23 files changed, 885 insertions(+), 1246 deletions(-) create mode 100644 de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM1.bin delete mode 100644 de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM1_v2.bin create mode 100644 de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM2.bin delete mode 100644 de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM2_v2.bin create mode 100644 de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM3.bin delete mode 100644 de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM3_v2.bin create mode 100644 de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM4.bin delete mode 100644 de4dot.code/deobfuscators/Agile_NET/vm/v2/MethodFinder.cs delete mode 100644 de4dot.code/deobfuscators/Agile_NET/vm/v2/MethodSigInfoCreator.cs delete mode 100644 de4dot.code/deobfuscators/Agile_NET/vm/v2/OpCodeHandler.cs create mode 100644 de4dot.code/deobfuscators/Agile_NET/vm/v2/SigCreator.cs diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj index 9f48a2e0..a56d2163 100644 --- a/de4dot.code/de4dot.code.csproj +++ b/de4dot.code/de4dot.code.csproj @@ -88,12 +88,10 @@ - - - + diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM1.bin b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM1.bin new file mode 100644 index 0000000000000000000000000000000000000000..e32fb05e59769d1424058351054b076896d3a2ab GIT binary patch literal 9154 zcmd6s32YTr6ozLI0TD`B%A!yOp#?2#%O;3Qp_ElC5F?8OjVKlYqedGyteUvs0vHvD zfXE`EP$PmtBLW7B1vQ!|K{jP6#6|^)8=~ItogVLf^QN>OpDX6)Z-$>yz(4Jy{L&PVC5mv!2e!F}nIzso=%>6HYn!{^onPj%E2#642io=WBl;;%EMR90)T}}U z%4bJ@d7eepDxa|^X1D|e?>gp&Lf-Z#GM;KNcZN_uC$dK*i=Nq9=h;1Cab&vw*@ttH ze(&_vJ3Jo=g8D(99f_dh=q-opovDskFsLKesz|@&-Z!UkTd(}PzJz+qeFIuohpxm& zP}fBA=ev`yPCZk9qEArAMD%BM=!#xJT@%Tldy~qRovA<3FQ{W8`m;K8JvT(xMDpij zsn7gzrv9uKqGKZZvpRIGpWwP`pI~blo}e3``c=J8NGeB}!6Sx;u2|5ZVXdJ%IxKJZ zNlCwE^R*YEZ#l4X*1P zs+)WCWbkflqqC}c2(A{T=cKatJgCDr{9R8phjMgQHxm)-@WvgTW1E_lV6T-3dg|%K z-r;?7{JJ&^(G@#Y!DmmH^d(9!)S*{9yPROSWQG7jYTIrGL@WGe@$=UKlAN@YnkJFtspd@RgP ztcP87)I43g-igEa7iVTi?bH{1zY}etjGyOxHL%BBrA?CZ+KwvCIlg6! zR6es9;jt?F%R)QDtmj`~{(wdXXffhHwHRJ;V?_LBHUubwQ@!wAu+s0_Gj*-Tnf1MD zf8G<)?6}C;0e4pR@1L+$VzaHYioULX?(?qoiw5&s zQ0*KP9&vXDpGAr^vkUH639T844cEROA4~cwId6*d1y612(gZEmSUvWcWvq;vw|TvA zNjEG1j0>EUi*V2xq1@iA%e>?tS8n?Cw@R~r{%!A~_RtU;btsn-I;wHd!Y98!b;Hoy zv{kXE00f#a&dj>Ar$n#LeA|8dk0OmqDLgMON0=cJ!ANt%qg{I0c)297gVpGG$uK*D zHvA{278#&}43B?NRwQ=pXl6umyL#fmt1c7yJDF9@&g??F;EB(B;hyHZo<7+i_QWG4 zsOxs_d_^h-{5i?or^obIf9Q6>aDIu*$}#xddLcRkM*F3+p{H8&E**>>jlAG|()353 zCrh@N^G0ED#>CHJqpXXe##^aI8IofM&G%65y6L+$d(%INd=rs(1a@QAWKK~?1TLTnHdK%&EG%DBC{MM7FTcM*_Ne;XV{(H z%_?z+7toI}c=p2M7;ABf<@p7EcmB^K#ZFLhql-7>!8KQRvAlbfW6Tg!`Sgp#@Pjo{ z6d~UQ+U$v%u{L>2Y zGgvP1F_zeO-=IeFzt?_$&r2NTzwgzR4()Ph#jQv#A9yVpJ8*>6@`@^=HunAXCyTn$ zL52Av(#IQK@EdaC2dDS#?;z1rrPKb$^Rt~Dd{@&Q(5mS9jcL!_d$J^LB6hs(>D5J^ zKfoZdG}gn8jKOcvbS5rEIu0mQwOfJijCJQ{dj3H36y!!$RO-2NX00KghIa(W1{w`{ z7u&h1sH^ooRet%LYx;VAP6(HZJRQr)fFo9ju4wRSaAIMq=MOSZ!nN}3TbT9a!{{bC zG&c_9l==N;S>)h2kj1M;=UC(rgFKzZv1QwW^n%9Q9;zMNQ($qTPwOc=gVktg2#4Ug zC2PycHk&K3uAI(cW*v^fc%)0yj1v65Icf0wjbmj;Ygdk?-Cv5lz0-+B*NIc(m)xZu YH6VXDf6UDlc52HWl4GtFE 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 diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM2.bin b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM2.bin new file mode 100644 index 0000000000000000000000000000000000000000..e1e577a5ff9b5cb6ff3eec15fb7beb43a67d69ae GIT binary patch literal 9138 zcmds+32YTr6ozLI0grMp#?2#i+~_1g;I7A2@yd9Mih%IQKO9;R!vZmJt`0Z z5sJ!IBZ2{=A_j^e8cmcSn~E&45mDlXsP}uP$9vzrDeaT0FHSPO^X|R>+3z`LroQKS zgU!w5%iz^CW3P70wrrc$w^+v-@29USX}2eX`--PVZ)bkO(btnaA5=w=H#Y^@Bb;5<$n|TfeS#wmM?LppICpEd7$Y-ImO4z4Fic66(zk^ln}mx)L8j zT@%Tlo5o+8dba*VpP-J3=+DZ~6}^JGCXzq**C{DHTYsWoP{%~{XJzPmeu%D#O4FyFI_IgQnwvH(g0|FOpymLC1(bC(G4o2hrL}u zWU@>4woiVg!1EiJU;hs)5z|C{HV@Qmp}h*dZD=*i&S z)<$PV^AKDuO3z7o?|D#%Z}_{OXb$D*tZpVE*5QpiI>$CLE5TkX5%kp4iM_-7=J<7O z9HJ|BD$A$;_Isb|jAoUkbCVFA6V1QjeOLVcZ5pC$qWZV8biN=&XR2qFq-wpmmo83g zta*woNWGlC=(!P6FUclkL0uuAVs~3nHJgby$dN=T7_yA5sMwj+j~{6JX2;C$f0sH= zRwLSw=-7$kJ4&+u$PMFV=|p5VyUBwMuHMi{ve_GbllhFQg1e(v+0jZ6CRTTrbW6drMR2A@TWG_wotSP88ei4E7j zyH3>kJZb0z=Zl@%)TIeptg-gSnT4!ezhKKo;gW7v{vH=NDHq|OGeWtwS(kaqH?G_t zb@O|@b|m|!U-vI*4GpnTn^GyEqZ$V-eCqh=u>*3`*2JCy5NN_UJ?ri+61_U}P3N6I zh%_pt@VvAXVTMQqBhA>yJ9M@2a#>&ptI_e2VRi&<_;*e%GC&6zp7^w+NbK0w%!uT6 z_2k1tt`zy(nN`ik>_WTXi68pxeNFbvI8`_H#3LoB8+Px0Q7Q!dImz5-#$3Mf>nVca z{1TbvWAM54LUaa<_Dg$1PqpUVIT$?}dBOQQlOKDAEZKDK>Vo2oF(1c9SqDRnw@{5T zB*zY#-=W;`-EY_JPk$%!4Mg4v*v-vuMq*IvHow$rNZh$_$otWm^X+4OH$>0S;mQo0 zx$G}!*y@fiIRnhvOs((LQe#+S1}UgcMfV>%WUG&vH1Ll6i9D8HdvD4+7|9Y6VV&YY z9vRl9JN6S~W*o>g|KRl&ndKm{xOyAUHal{7s@>VytP*#40sR<*XD>XCu@;wDo?qbi z=KVBG>;x4zx_Be*S9NU%%lq!|39mKze>xXC|m^{?w6O z74P}ooSk@_742pi-45!9o#~q`@(KrujTGtm-JO;4XcoOUe4VA)BMxNtxKSk*d8I)H zdj~Xk?TrP=^0EB_{&v4L*>iyxp{v>vFMP$CuYO literal 0 HcmV?d00001 diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM2_v2.bin b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM2_v2.bin deleted file mode 100644 index 81bd5ae61b634bf895c08f7254eacd511e1bd157..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9520 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 Uuh}WiTb^L3_btHqKmzdp07N>HDF6Tf diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM3.bin b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM3.bin new file mode 100644 index 0000000000000000000000000000000000000000..7378faf9805d0c9a395f7c9df1ca71887011d8a7 GIT binary patch literal 9186 zcmds+32YTr6ozLI0gidogVLf^QN>0c|NF`A}3aSGup#zjDrocmdpq{^Blf9GJYZ)G)U3h< z&ZkD6JkO%)RnAxxGhBi~b^~+6VeHmNG9GI)e}-^BEkYxjMbB((@Wj{Radf)oi3f7g ze#f+u4?Q0Zg7(25ibSw+{0Dm)ove*`FlZy*s>;5kep8aUZB+i*Si-&C&LQnWWs zb@uNk8_z}|HYQ>`Ys1#Y32v+Q3HB@_5_AKcel_nCnpC39;E}^4moIACtlr2EJ1^__ z@s@$D7iup=-?D4voDDp4rnQ_pX`AOabfI&-2d1Ozw!BsLn!?%C6BC7RZ6bgW#GH9Xlof&*yPUQlKtLUVj_Rxm)Z$k)$oq~)+3w^tTdi~N%E#GD_f1tIsBsNz)G|ZA|3}PCdk1O&!JbB=blp$oY zr6O{gfviX*k@QNR#y5k>-11VVwZG=wU~`XEE}=y`^5LtwYk%{6lb$g>2)XLk9^Dzd z+uH1`X&pkUMd?1N?mZ9g$PItj6U*ToUDeG*#5=rkN7vX^W+m8bC4!y0JMnjT-yFZK ztwU_ZPgTYA-+u2?o3X66Y(68z=0uBcc;6L&eA|TBnyB%uEt}hh*v#o!C#l|G?j?)U zT5Fx63UXe~TJ+2na$ZtRsDipeJ;m?#MAd30(V#|>rC_Ks_C&?ctbTfT*Ef1*9{yd< zajF{GhDHYtmEBm8{YP$?EXyaNyP>8IwivXomFVftF51<6tITSR8_}WVtmqmpUlz|a zd}Ll~occjW_nTz@MiWw*7i7CQkOy-XOt8ol2dVp6zX{68l4>aMi&lI*3?<&fuR3a- zuHWd$-h0Y2GqT!`P7%B9xrKEa3%=i3FHD)es#s1sLlWV+I{S+vJHxE!pJo1_2QtAj z5-;@-QE+oY;$#Q{9Kop_#432Q@BI4awVGEp)@p6rN3MAA{G8lxt##-kGvMruoP_={$Ss30$L}$E8GLX#Sn0YoGgj`}*gG^DL;24vL7ll)>MkMVg^PI$pwRMsmaT z??;E4e3>-1!1-dQK6QD57H^bXJ-e8d%NM-2UZkX(mA@wiNh(Do=!|ggWY%R~>W!=S zC;j}vukOqK>DL|4b%KZZsB@*3@KK9{9zJ&P__ZT*(^kjs0uWfjI4kS6K9apU^Ifm4 zKZ-W0rO513i7-PXgVE;NhkEq2`Ep)>g4O7J$uJZ_AO4+Piw^KXhlf9}C>1|;H8Y~Q zT|IK&mx4p(N7 z%w?b8VNZ8r$sS?0b%y%(OxWGz=s^WM@U zhbP9b@_!m9enqOAjl4k*uUpc?>e{;!V}_WMl8VT8pHaK(Br8I`dGv8mAU(gYGZXYq z;f$;LD&F(^Ih14wE86`qx*gY#ThrgM$O{}KK2@aW_jgvR<5~Lt_%)X2fH;uZlP6SI zEdiBuJ*2+OOM7=ZMm!lSSv4aYWN2Jd;vXD38 z$PZ3$JlH{Er)sDDlILeT6nuA63V2oZd(|yZ-gRtC+9dpV)8i$joh?J@#9V^LzBi@KU0g==6$l_GbA7*}u)at8sQP!gmV4Kw3+&GX03kS}z$l-Ay z%T|xivB(hy8H}&%aeR4hVR~VUP50N2?LqK3*{A0(l)=+$WQc^|zNN~`&NjqVcvp7k zC1xFo!F;5v(~1)O{yBO0n=N8>$7)xP7kfP$dAp}`lllP#kvyKa^mdIXQ==;9%@8@e RH9K{5D|50uUDtb$0iELRzvP6&N4TT7WsMlVU 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 D(I=s5 diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM4.bin b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM4.bin new file mode 100644 index 0000000000000000000000000000000000000000..85439b6e8b07a477d7d71b0783d97e660619517d GIT binary patch literal 9328 zcmds+32YTr6ozLI0gL7~O=+K0eQ}cMopf;JzzuXQ&+VxP*y19rwh%_>~r ze17DY=UG&>(iw|lhD%V$u3>IC4BIg~f4c|IBh?SnrQiD2W%&EM5JR~zwQ&_=vfmVHUxCnR&*sQk0BgnRRSeOpw9t>j10 z)y#9pYdofI&-#8=_14DpVQ9TrMkqYT|J{6xv0L=K9Lx>v05^{Fy)ox)x9>? zZnr`_0)iWV5*v+VhwQ1-iKg`%9V?e)4Zmz2!2z^tFDNq+q4|A$R5(VW z)lvb;OYMYisyU;F^$2GJE47zgo4j@V>W0H|jy*3ruoA5Uxk>$D)@sfS`eGYgMh}0d zfXswSXgegoT;Tcj&9DE57s;Og%8Lz*7s&(7Me>5^x_KC^8N@U^A79REx%lvml)hxL zr6O{gfviX*k@RZU+LOU#Zhx`OhF?eDZgY=SE}=y`@?rPF4ZnH5Nza%bgj{uNkM0cK zZEbc|v<@NFqI92>_nrrL4c%~)1hHa8BjInm-9-gm_x-zFipCTe^u%jTvbHgkGbNvhU|d)11x zMp~z+f}EFgmp^rboR?G+s-Uh=Pw~4wQMH;$G^mkeDHy7ZJyG#9tDoJ|?yXLl$Ii$( zPE{k@(CF~d;yX&R|HuuKW%)#OH`LU@`d4pkD0;fH%fGF+LuR$c4Q$z9ZgdToFN@6# zADNdLr+(1U{U+I?)~HnG1=&0fAI1>f(i7beVGQz$2$A&Kx@oBd^honhAVFE)SB1DRkM ziI;kaD7ZNxaWVt}j^NY|Vii2u_wAXyLG#MSTCHt5`-X?E$jSZ2T8Az&V;*Drwjx=Zl^C)a40Uys_@)d4;TuSo*;xk&K zm;D6~d%6=#_5icCQtNxQoH491gBF}lMKcc^u&0liH1JORi9D8n_KwNhAE^?OVOPX~ zJUF~-5Bw*{%s7x~{{9gbndKnyxJH}EHb40NEKAwhtZGcKk7xw| zvu^69c+cn+coaUiqDk1Daq zs|*s4qY2)o(qOskZ#>AU5Zhls?S7lG`-mL_U$u_>;;YxBk59fNI}$9H#2ESe?&)7o z{x{p}uX)id?`^N9bacI)754;l~iO=@m#9LPz_dM&WX0dXLU z*N)7w$bkkKjIZl)eAy~LJ-`0e2dc;RAb6bY)AJX~;OR9eL_%=iQsrf58{#s&E4%Yr zvrepn`AAo%6(#unbNqm}>&NPjm98GocYZqZc2DPK&lOGvmkNJGS1Rm>g1hWDAu1kO pA>Dy_h|rh)Jr%iJQpwO2i;0`)$6Dm_2b-ay`Id6)!q08&{{()n0pb7v literal 0 HcmV?d00001 diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CompositeHandlerDetector.cs b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CompositeHandlerDetector.cs index 9ae1debc..fc0452e6 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CompositeHandlerDetector.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CompositeHandlerDetector.cs @@ -25,19 +25,17 @@ using de4dot.blocks; namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { class CompositeHandlerDetector { - readonly List handlers; + readonly List handlers; - public CompositeHandlerDetector(IList handlers) { - this.handlers = new List(handlers.Count); - OpCodeHandler nop = null; - foreach (var handler in handlers) { - if (nop == null && handler.OpCodeHandlerInfo.TypeCode == HandlerTypeCode.Nop) - nop = handler; - else - this.handlers.Add(handler); - } - if (nop != null) - this.handlers.Add(nop); + public CompositeHandlerDetector(IList handlers) { + this.handlers = new List(handlers); + + this.handlers.Sort((a, b) => { + int r = b.BlockSigInfos.Count.CompareTo(a.BlockSigInfos.Count); + if (r != 0) + return r; + return b.BlockSigInfos[0].Hashes.Count.CompareTo(a.BlockSigInfos[0].Hashes.Count); + }); } struct MatchState { @@ -51,27 +49,18 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { } struct HandlerState { - public readonly HandlerMethod HandlerMethod; - public readonly IList Blocks; + public readonly List BlockSigInfos; public readonly int BlockIndex; - public int InstructionIndex; + public int HashIndex; - public HandlerState(HandlerMethod handlerMethod, int blockIndex, int instructionIndex) { - this.HandlerMethod = handlerMethod; - this.Blocks = handlerMethod.Blocks.MethodBlocks.GetAllBlocks(); + public HandlerState(List blockSigInfos, int blockIndex, int instructionIndex) { + this.BlockSigInfos = blockSigInfos; this.BlockIndex = blockIndex; - this.InstructionIndex = instructionIndex; - } - - public HandlerState(HandlerMethod handlerMethod, IList blocks, int blockIndex, int instructionIndex) { - this.HandlerMethod = handlerMethod; - this.Blocks = blocks; - this.BlockIndex = blockIndex; - this.InstructionIndex = instructionIndex; + this.HashIndex = instructionIndex; } public HandlerState Clone() { - return new HandlerState(HandlerMethod, Blocks, BlockIndex, InstructionIndex); + return new HandlerState(BlockSigInfos, BlockIndex, HashIndex); } } @@ -98,22 +87,22 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { } public bool FindHandlers(CompositeOpCodeHandler composite) { - composite.OpCodeHandlerInfos.Clear(); - var compositeExecState = new FindHandlerState(new HandlerState(composite.ExecMethod, 0, 0)); + composite.TypeCodes.Clear(); + var compositeExecState = new FindHandlerState(new HandlerState(composite.BlockSigInfos, 0, 0)); while (!compositeExecState.Done) { var handler = FindHandlerMethod(ref compositeExecState); if (handler == null) return false; - composite.OpCodeHandlerInfos.Add(handler.OpCodeHandlerInfo); + composite.TypeCodes.Add(handler.TypeCode); } - return composite.OpCodeHandlerInfos.Count != 0; + return composite.TypeCodes.Count != 0; } - OpCodeHandler FindHandlerMethod(ref FindHandlerState findExecState) { + MethodSigInfo FindHandlerMethod(ref FindHandlerState findExecState) { foreach (var handler in handlers) { FindHandlerState findExecStateNew = findExecState.Clone(); - if (!Matches(handler.ExecMethod, ref findExecStateNew)) + if (!Matches(handler.BlockSigInfos, ref findExecStateNew)) continue; findExecState = findExecStateNew; @@ -123,14 +112,14 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { } Stack stack = new Stack(); - bool Matches(HandlerMethod handler, ref FindHandlerState findState) { + bool Matches(List handler, ref FindHandlerState findState) { HandlerState? nextState = null; stack.Clear(); stack.Push(new MatchState(new HandlerState(handler, 0, 0), findState.CompositeState)); while (stack.Count > 0) { var matchState = stack.Pop(); - if (matchState.CompositeState.InstructionIndex == 0) { + if (matchState.CompositeState.HashIndex == 0) { if (findState.VisitedCompositeBlocks.ContainsKey(matchState.CompositeState.BlockIndex)) continue; findState.VisitedCompositeBlocks[matchState.CompositeState.BlockIndex] = true; @@ -143,193 +132,83 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { if (!Compare(ref matchState.OtherState, ref matchState.CompositeState)) return false; - var hblock = matchState.OtherState.Blocks[matchState.OtherState.BlockIndex]; - var hinstrs = hblock.Instructions; - int hi = matchState.OtherState.InstructionIndex; - var cblock = matchState.CompositeState.Blocks[matchState.CompositeState.BlockIndex]; - var cinstrs = cblock.Instructions; - int ci = matchState.CompositeState.InstructionIndex; + var hblock = matchState.OtherState.BlockSigInfos[matchState.OtherState.BlockIndex]; + var hinstrs = hblock.Hashes; + int hi = matchState.OtherState.HashIndex; + var cblock = matchState.CompositeState.BlockSigInfos[matchState.CompositeState.BlockIndex]; + var cinstrs = cblock.Hashes; + int ci = matchState.CompositeState.HashIndex; if (hi < hinstrs.Count) return false; if (ci < cinstrs.Count) { - if (hblock.CountTargets() != 0) + if (hblock.Targets.Count != 0) return false; - if (hblock.LastInstr.OpCode.Code == Code.Ret) { + if (hblock.EndsInRet) { if (nextState != null) return false; nextState = matchState.CompositeState; } } else { - if (cblock.CountTargets() != hblock.CountTargets()) + if (cblock.Targets.Count != hblock.Targets.Count) + return false; + if (cblock.HasFallThrough != hblock.HasFallThrough) return false; - if (cblock.FallThrough != null || hblock.FallThrough != null) { - if (cblock.FallThrough == null || hblock.FallThrough == null) - return false; - var hs = CreateHandlerState(handler, matchState.OtherState.Blocks, hblock.FallThrough); - var cs = CreateHandlerState(findState.CompositeState.HandlerMethod, findState.CompositeState.Blocks, cblock.FallThrough); + for (int i = 0; i < cblock.Targets.Count; i++) { + var hs = new HandlerState(handler, hblock.Targets[i], 0); + var cs = new HandlerState(findState.CompositeState.BlockSigInfos, cblock.Targets[i], 0); stack.Push(new MatchState(hs, cs)); } - if (cblock.Targets != null || hblock.Targets != null) { - if (cblock.Targets == null || hblock.Targets == null || - cblock.Targets.Count != hblock.Targets.Count) - return false; - - for (int i = 0; i < cblock.Targets.Count; i++) { - var hs = CreateHandlerState(handler, matchState.OtherState.Blocks, hblock.Targets[i]); - var cs = CreateHandlerState(findState.CompositeState.HandlerMethod, findState.CompositeState.Blocks, cblock.Targets[i]); - stack.Push(new MatchState(hs, cs)); - } - } } } if (nextState == null) { + if (findState.VisitedCompositeBlocks.Count != findState.CompositeState.BlockSigInfos.Count) + return false; findState.Done = true; return true; } else { if (findState.CompositeState.BlockIndex == nextState.Value.BlockIndex && - findState.CompositeState.InstructionIndex == nextState.Value.InstructionIndex) + findState.CompositeState.HashIndex == nextState.Value.HashIndex) return false; findState.CompositeState = nextState.Value; + if (findState.CompositeState.HashIndex == 0) + findState.VisitedCompositeBlocks.Remove(findState.CompositeState.BlockIndex); return true; } } - static HandlerState CreateHandlerState(HandlerMethod handler, IList blocks, Block target) { - return new HandlerState(handler, blocks.IndexOf(target), 0); - } - static bool Compare(ref HandlerState handler, ref HandlerState composite) { - var hinstrs = handler.Blocks[handler.BlockIndex].Instructions; - int hi = handler.InstructionIndex; - var cinstrs = composite.Blocks[composite.BlockIndex].Instructions; - int ci = composite.InstructionIndex; + var hhashes = handler.BlockSigInfos[handler.BlockIndex].Hashes; + int hi = handler.HashIndex; + var chashes = composite.BlockSigInfos[composite.BlockIndex].Hashes; + int ci = composite.HashIndex; while (true) { - if (hi >= hinstrs.Count && ci >= cinstrs.Count) + if (hi >= hhashes.Count && ci >= chashes.Count) break; - if (hi >= hinstrs.Count || ci >= cinstrs.Count) + + if (hi >= hhashes.Count) { + if (handler.BlockSigInfos[handler.BlockIndex].EndsInRet) + break; + } + + if (hi >= hhashes.Count || ci >= chashes.Count) return false; - var hinstr = hinstrs[hi++]; - var cinstr = cinstrs[ci++]; - if (hinstr.OpCode.Code == Code.Nop || - cinstr.OpCode.Code == Code.Nop) { - if (hinstr.OpCode.Code != Code.Nop) - hi--; - if (cinstr.OpCode.Code != Code.Nop) - ci--; - continue; - } + var hhash = hhashes[hi++]; + var chash = chashes[ci++]; - if (hi == hinstrs.Count && hinstr.OpCode.Code == Code.Ret) { - if (cinstr.OpCode.Code != Code.Br && cinstr.OpCode.Code != Code.Ret) - ci--; - break; - } - - if (hinstr.OpCode.Code != cinstr.OpCode.Code) - return false; - - if (hinstr.OpCode.Code == Code.Ldfld && - hi + 1 < hinstrs.Count && ci + 1 < cinstrs.Count) { - var hfield = hinstr.Operand as FieldDef; - var cfield = cinstr.Operand as FieldDef; - if (hfield != null && cfield != null && - !hfield.IsStatic && !cfield.IsStatic && - hfield.DeclaringType == handler.HandlerMethod.Method.DeclaringType && - cfield.DeclaringType == composite.HandlerMethod.Method.DeclaringType && - SignatureEqualityComparer.Instance.Equals(hfield.Signature, cfield.Signature)) { - cinstr = cinstrs[ci++]; - hinstr = hinstrs[hi++]; - if (cinstr.OpCode.Code != Code.Ldc_I4 || - hinstr.OpCode.Code != Code.Ldc_I4) - return false; - continue; - } - } - - if (!CompareOperand(hinstr.OpCode.OperandType, cinstr.Operand, hinstr.Operand)) + if (chash != hhash) return false; } - handler.InstructionIndex = hi; - composite.InstructionIndex = ci; + handler.HashIndex = hi; + composite.HashIndex = ci; return true; } - - static bool CompareOperand(OperandType opType, object a, object b) { - switch (opType) { - case OperandType.ShortInlineI: - return (a is byte && b is byte && (byte)a == (byte)b) || - (a is sbyte && b is sbyte && (sbyte)a == (sbyte)b); - - case OperandType.InlineI: - return a is int && b is int && (int)a == (int)b; - - case OperandType.InlineI8: - return a is long && b is long && (long)a == (long)b; - - case OperandType.ShortInlineR: - return a is float && b is float && (float)a == (float)b; - - case OperandType.InlineR: - return a is double && b is double && (double)a == (double)b; - - case OperandType.InlineField: - return FieldEqualityComparer.CompareDeclaringTypes.Equals(a as IField, b as IField); - - case OperandType.InlineMethod: - return MethodEqualityComparer.CompareDeclaringTypes.Equals(a as IMethod, b as IMethod); - - case OperandType.InlineSig: - return SignatureEqualityComparer.Instance.Equals(a as MethodSig, b as MethodSig); - - case OperandType.InlineString: - return string.Equals(a as string, b as string); - - case OperandType.InlineSwitch: - var al = a as IList; - var bl = b as IList; - return al != null && bl != null && al.Count == bl.Count; - - case OperandType.InlineTok: - var fa = a as IField; - var fb = b as IField; - if (fa != null && fb != null) - return FieldEqualityComparer.CompareDeclaringTypes.Equals(fa, fb); - var ma = a as IMethod; - var mb = b as IMethod; - if (ma != null && mb != null) - return MethodEqualityComparer.CompareDeclaringTypes.Equals(ma, mb); - return TypeEqualityComparer.Instance.Equals(a as ITypeDefOrRef, b as ITypeDefOrRef); - - case OperandType.InlineType: - return TypeEqualityComparer.Instance.Equals(a as ITypeDefOrRef, b as ITypeDefOrRef); - - case OperandType.InlineVar: - case OperandType.ShortInlineVar: - var la = a as Local; - var lb = b as Local; - if (la != null && lb != null) - return true; - var pa = a as Parameter; - var pb = b as Parameter; - return pa != null && pb != null && pa.Index == pb.Index; - - case OperandType.InlineBrTarget: - case OperandType.ShortInlineBrTarget: - case OperandType.InlineNone: - case OperandType.InlinePhi: - return true; - - default: - return false; - } - } } } diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CompositeOpCodeHandler.cs b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CompositeOpCodeHandler.cs index 2508d020..cc6afe0e 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CompositeOpCodeHandler.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CompositeOpCodeHandler.cs @@ -23,45 +23,17 @@ using dnlib.DotNet; using de4dot.blocks; namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { - class HandlerMethod { - public MethodDef Method { get; private set; } - public Blocks Blocks { get; private set; } - - public HandlerMethod(MethodDef method) { - this.Method = method; - this.Blocks = new Blocks(method); - } - } - - class PrimitiveHandlerMethod : HandlerMethod { - public MethodSigInfo Sig { get; set; } - - public PrimitiveHandlerMethod(MethodDef method) - : base(method) { - } - } - class CompositeOpCodeHandler { - public TypeDef HandlerType { get; private set; } - public HandlerMethod ExecMethod { get; private set; } - public List OpCodeHandlerInfos { get; private set; } + public List BlockSigInfos { get; private set; } + public List TypeCodes { get; private set; } - public CompositeOpCodeHandler(TypeDef handlerType, HandlerMethod execMethod) { - this.HandlerType = handlerType; - this.ExecMethod = execMethod; - this.OpCodeHandlerInfos = new List(); + public CompositeOpCodeHandler(List blockSigInfos) { + this.BlockSigInfos = blockSigInfos; + this.TypeCodes = new List(); } public override string ToString() { - if (OpCodeHandlerInfos.Count == 0) - return ""; - var sb = new StringBuilder(); - foreach (var handler in OpCodeHandlerInfos) { - if (sb.Length != 0) - sb.Append(", "); - sb.Append(handler.Name); - } - return sb.ToString(); + return OpCodeHandlerInfo.GetCompositeName(TypeCodes); } } } diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmInfo.cs b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmInfo.cs index 815cc53d..a5d1c557 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmInfo.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmInfo.cs @@ -594,45 +594,79 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { } public bool FindUnaryOpsMethods() { - UnaryNot = FindUnaryOpMethod(Code.Not); - UnaryNeg = FindUnaryOpMethod(Code.Neg); - return UnaryNot != null && UnaryNeg != null; + UnaryNot = FindUnaryOpMethod1(Code.Not); + UnaryNeg = FindUnaryOpMethod1(Code.Neg); + if (UnaryNot != null && UnaryNeg != null) + return true; + + return FindUnaryOpMethod2(); } - MethodDef FindUnaryOpMethod(Code code) { + MethodDef FindUnaryOpMethod1(Code code) { foreach (var type in module.Types) { if (type.BaseType != VmHandlerBaseType) continue; if (type.Methods.Count != 4) continue; - foreach (var method in type.Methods) { - if (!method.HasBody || !method.IsStatic) - continue; - if (!DotNetUtils.IsMethod(method, "System.Object", "(System.Object)")) - continue; - if (CountThrows(method) != 1) - continue; - var instrs = method.Body.Instructions; - for (int i = 0; i < instrs.Count - 4; i++) { - var ldarg = instrs[i]; - if (!ldarg.IsLdarg() || ldarg.GetParameterIndex() != 0) - continue; - if (!CheckUnboxAny(instrs[i + 1], ElementType.I4)) - continue; - if (instrs[i + 2].OpCode.Code != code) - continue; - if (!CheckBox(instrs[i + 3], ElementType.I4)) - continue; - if (!instrs[i + 4].IsStloc()) - continue; - - return method; - } - } + var method = FindUnaryMethod(type, code); + if (method != null) + return method; } return null; } + bool FindUnaryOpMethod2() { + foreach (var type in module.Types) { + if (type.BaseType == null || type.BaseType.FullName != "System.Object") + continue; + if (type.Methods.Count != 3) + continue; + + UnaryNot = FindUnaryMethod(type, Code.Not); + UnaryNeg = FindUnaryMethod(type, Code.Neg); + if (UnaryNot != null && UnaryNeg != null) + return true; + } + return false; + } + + MethodDef FindUnaryMethod(TypeDef type, Code code) { + foreach (var method in type.Methods) { + if (!IsUnsaryMethod(method, code)) + continue; + + return method; + } + return null; + } + + bool IsUnsaryMethod(MethodDef method, Code code) { + if (!method.HasBody || !method.IsStatic) + return false; + if (!DotNetUtils.IsMethod(method, "System.Object", "(System.Object)")) + return false; + if (CountThrows(method) != 1) + return false; + var instrs = method.Body.Instructions; + for (int i = 0; i < instrs.Count - 4; i++) { + var ldarg = instrs[i]; + if (!ldarg.IsLdarg() || ldarg.GetParameterIndex() != 0) + continue; + if (!CheckUnboxAny(instrs[i + 1], ElementType.I4)) + continue; + if (instrs[i + 2].OpCode.Code != code) + continue; + if (!CheckBox(instrs[i + 3], ElementType.I4)) + continue; + if (!instrs[i + 4].IsStloc()) + continue; + + return true; + } + + return false; + } + static int CountThrows(MethodDef method) { if (method == null || method.Body == null) return 0; diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmResources.Designer.cs b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmResources.Designer.cs index 6153040b..3a090f84 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmResources.Designer.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmResources.Designer.cs @@ -63,9 +63,9 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { /// /// Looks up a localized resource of type System.Byte[]. /// - internal static byte[] CSVM1_v2 { + internal static byte[] CSVM1 { get { - object obj = ResourceManager.GetObject("CSVM1_v2", resourceCulture); + object obj = ResourceManager.GetObject("CSVM1", resourceCulture); return ((byte[])(obj)); } } @@ -73,9 +73,9 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { /// /// Looks up a localized resource of type System.Byte[]. /// - internal static byte[] CSVM2_v2 { + internal static byte[] CSVM2 { get { - object obj = ResourceManager.GetObject("CSVM2_v2", resourceCulture); + object obj = ResourceManager.GetObject("CSVM2", resourceCulture); return ((byte[])(obj)); } } @@ -83,9 +83,19 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { /// /// Looks up a localized resource of type System.Byte[]. /// - internal static byte[] CSVM3_v2 { + internal static byte[] CSVM3 { get { - object obj = ResourceManager.GetObject("CSVM3_v2", resourceCulture); + object obj = ResourceManager.GetObject("CSVM3", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] CSVM4 { + get { + object obj = ResourceManager.GetObject("CSVM4", resourceCulture); return ((byte[])(obj)); } } diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmResources.resx b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmResources.resx index 254aef83..17159be0 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmResources.resx +++ b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmResources.resx @@ -117,14 +117,17 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - CSVM1_v2.bin;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + CSVM1.bin;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - CSVM2_v2.bin;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + CSVM2.bin;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - CSVM3_v2.bin;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + CSVM3.bin;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + CSVM4.bin;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 \ No newline at end of file diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmToCilMethodConverter.cs b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmToCilMethodConverter.cs index 3cc2f2f6..7d76cf59 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmToCilMethodConverter.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmToCilMethodConverter.cs @@ -45,11 +45,11 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { uint offset = 0; for (int vmInstrIndex = 0; vmInstrIndex < numVmInstrs; vmInstrIndex++) { var composite = opCodeDetector.Handlers[vmInstrs[vmInstrIndex]]; - var handlerInfos = composite.OpCodeHandlerInfos; + IList handlerInfos = composite.HandlerTypeCodes; if (handlerInfos.Count == 0) - handlerInfos = new List() { new OpCodeHandlerInfo(HandlerTypeCode.Nop, null) }; + handlerInfos = new HandlerTypeCode[] { HandlerTypeCode.Nop }; for (int hi = 0; hi < handlerInfos.Count; hi++) { - var instr = handlerInfoReader.Read(handlerInfos[hi].TypeCode, reader); + var instr = handlerInfoReader.Read(handlerInfos[hi], reader); instr.Offset = offset; offset += (uint)GetInstructionSize(instr); SetCilToVmIndex(instr, vmInstrIndex); @@ -58,6 +58,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { instrs.Add(instr); } } + return instrs; } } diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/MethodFinder.cs b/de4dot.code/deobfuscators/Agile_NET/vm/v2/MethodFinder.cs deleted file mode 100644 index ca206830..00000000 --- a/de4dot.code/deobfuscators/Agile_NET/vm/v2/MethodFinder.cs +++ /dev/null @@ -1,109 +0,0 @@ -/* - Copyright (C) 2011-2013 de4dot@gmail.com - - This file is part of de4dot. - - de4dot is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - de4dot is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with de4dot. If not, see . -*/ - -using System.Collections.Generic; - -namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { - class MethodFinder { - readonly IList handlerInfos; - readonly PrimitiveHandlerMethod handlerMethod; - - class SigState { - public readonly MethodSigInfo SigInfo; - - public SigState(PrimitiveHandlerMethod handlerMethod) { - this.SigInfo = handlerMethod.Sig; - } - } - - public MethodFinder(IList handlerInfos, PrimitiveHandlerMethod handlerMethod) { - this.handlerInfos = handlerInfos; - this.handlerMethod = handlerMethod; - } - - public OpCodeHandler FindHandler() { - var handler = FindHandler(new SigState(handlerMethod)); - if (handler == null) - return null; - - return new OpCodeHandler(handler, handlerMethod.Method.DeclaringType, handlerMethod); - } - - OpCodeHandlerInfo FindHandler(SigState execSigState) { - foreach (var handler in handlerInfos) { - if (Matches(handler.ExecSig, execSigState)) - return handler; - } - return null; - } - - struct MatchInfo { - public int HandlerIndex; - public int SigIndex; - - public MatchInfo(int handlerIndex, int sigIndex) { - this.HandlerIndex = handlerIndex; - this.SigIndex = sigIndex; - } - } - - Dictionary sigIndexToHandlerIndex = new Dictionary(); - Dictionary handlerIndexToSigIndex = new Dictionary(); - Stack stack = new Stack(); - bool Matches(MethodSigInfo handlerSig, SigState sigState) { - stack.Clear(); - sigIndexToHandlerIndex.Clear(); - handlerIndexToSigIndex.Clear(); - var handlerInfos = handlerSig.BlockInfos; - var sigInfos = sigState.SigInfo.BlockInfos; - - stack.Push(new MatchInfo(0, 0)); - while (stack.Count > 0) { - var info = stack.Pop(); - - int handlerIndex, sigIndex; - bool hasVisitedHandler = handlerIndexToSigIndex.TryGetValue(info.HandlerIndex, out sigIndex); - bool hasVisitedSig = sigIndexToHandlerIndex.TryGetValue(info.SigIndex, out handlerIndex); - if (hasVisitedHandler != hasVisitedSig) - return false; - if (hasVisitedHandler) { - if (handlerIndex != info.HandlerIndex || sigIndex != info.SigIndex) - return false; - continue; - } - handlerIndexToSigIndex[info.HandlerIndex] = info.SigIndex; - sigIndexToHandlerIndex[info.SigIndex] = info.HandlerIndex; - - var handlerBlock = handlerInfos[info.HandlerIndex]; - var sigBlock = sigInfos[info.SigIndex]; - - if (!handlerBlock.Equals(sigBlock)) - return false; - - for (int i = 0; i < handlerBlock.Targets.Count; i++) { - int handlerTargetIndex = handlerBlock.Targets[i]; - int sigTargetIndex = sigBlock.Targets[i]; - stack.Push(new MatchInfo(handlerTargetIndex, sigTargetIndex)); - } - } - - return true; - } - } -} diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/MethodSigInfoCreator.cs b/de4dot.code/deobfuscators/Agile_NET/vm/v2/MethodSigInfoCreator.cs deleted file mode 100644 index c311e0a9..00000000 --- a/de4dot.code/deobfuscators/Agile_NET/vm/v2/MethodSigInfoCreator.cs +++ /dev/null @@ -1,737 +0,0 @@ -/* - Copyright (C) 2011-2013 de4dot@gmail.com - - This file is part of de4dot. - - de4dot is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - de4dot is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with de4dot. If not, see . -*/ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Security.Cryptography; -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using dnlib.DotNet.MD; -using de4dot.blocks; - -namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { - class MethodSigInfo { - readonly List blockInfos; - - public List BlockInfos { - get { return blockInfos; } - } - - public MethodSigInfo() { - this.blockInfos = new List(); - } - - public MethodSigInfo(IEnumerable blockInfos) { - this.blockInfos = new List(blockInfos); - } - } - - class BlockInfo : IEquatable { - readonly List targets; - - public byte[] Hash { get; set; } - public List Targets { - get { return targets; } - } - - public BlockInfo() { - this.targets = new List(); - } - - public BlockInfo(byte[] hash, IEnumerable targets) { - this.Hash = hash; - this.targets = new List(targets); - } - - public override string ToString() { - if (Hash == null) - return ""; - return BitConverter.ToString(Hash).Replace("-", string.Empty); - } - - public bool Equals(BlockInfo other) { - return Equals(Hash, other.Hash) && - Targets.Count == other.Targets.Count; - } - - bool Equals(byte[] a, byte[] b) { - if (a == b) - return true; - if (a == null || b == null) - return false; - if (a.Length != b.Length) - return false; - for (int i = 0; i < a.Length; i++) { - if (a[i] != b[i]) - return false; - } - return true; - } - } - - class MethodSigInfoCreator { - MethodSigInfo methodSigInfo; - Blocks blocks; - IList allBlocks; - Dictionary blockToInfo; - Dictionary methodToId = new Dictionary(); - - public void AddId(object key, int id) { - if (key != null) - methodToId[key] = id; - } - - int GetId(object key) { - if (key == null) - return int.MinValue; - - int id; - if (methodToId.TryGetValue(key, out id)) - return id; - return int.MinValue + 1; - } - - public MethodSigInfo Create(Blocks blocks) { - methodSigInfo = new MethodSigInfo(); - - this.blocks = blocks; - allBlocks = blocks.MethodBlocks.GetAllBlocks(); - - blockToInfo = new Dictionary(); - foreach (var block in allBlocks) { - var blockInfo = new BlockInfo(); - blockToInfo[block] = blockInfo; - methodSigInfo.BlockInfos.Add(blockInfo); - } - - foreach (var block in allBlocks) { - var blockInfo = blockToInfo[block]; - Update(blockInfo, block); - if (block.FallThrough != null) - blockInfo.Targets.Add(allBlocks.IndexOf(block.FallThrough)); - if (block.Targets != null) { - foreach (var target in block.Targets) - blockInfo.Targets.Add(allBlocks.IndexOf(target)); - } - } - - return methodSigInfo; - } - - void Update(BlockInfo blockInfo, Block block) { - using (var hasher = MD5.Create()) { - bool emptyHash; - using (var outStream = new NullStream()) { - using (var csStream = new CryptoStream(outStream, hasher, CryptoStreamMode.Write)) { - var writer = new BinaryWriter(csStream); - Update(writer, blockInfo, block); - } - emptyHash = outStream.Length == 0; - } - if (!emptyHash) - blockInfo.Hash = hasher.Hash; - } - } - - void Update(BinaryWriter writer, BlockInfo blockInfo, Block block) { - var instrs = block.Instructions; - for (int i = 0; i < instrs.Count; i++) { - var instr = instrs[i]; - switch (instr.OpCode.Code) { - case Code.Beq_S: - case Code.Bge_S: - case Code.Bgt_S: - case Code.Ble_S: - case Code.Blt_S: - case Code.Bne_Un_S: - case Code.Bge_Un_S: - case Code.Bgt_Un_S: - case Code.Ble_Un_S: - case Code.Blt_Un_S: - case Code.Brfalse_S: - case Code.Brtrue_S: - case Code.Leave_S: - case Code.Beq: - case Code.Bge: - case Code.Bgt: - case Code.Ble: - case Code.Blt: - case Code.Bne_Un: - case Code.Bge_Un: - case Code.Bgt_Un: - case Code.Ble_Un: - case Code.Blt_Un: - case Code.Brfalse: - case Code.Brtrue: - case Code.Leave: - writer.Write((ushort)SimplifyBranch(instr.OpCode.Code)); - break; - - case Code.Switch: - writer.Write((ushort)instr.OpCode.Code); - writer.Write(blockInfo.Targets.Count); - break; - - case Code.Br_S: - case Code.Br: - break; - - case Code.Ret: - break; - - case Code.Ldc_I4_M1: - case Code.Ldc_I4_0: - case Code.Ldc_I4_1: - case Code.Ldc_I4_2: - case Code.Ldc_I4_3: - case Code.Ldc_I4_4: - case Code.Ldc_I4_5: - case Code.Ldc_I4_6: - case Code.Ldc_I4_7: - case Code.Ldc_I4_8: - case Code.Ldc_I4: - case Code.Ldc_I4_S: - writer.Write((ushort)Code.Ldc_I4); - writer.Write(instr.GetLdcI4Value()); - break; - - case Code.Ldc_I8: - writer.Write((ushort)instr.OpCode.Code); - writer.Write((long)instr.Operand); - break; - - case Code.Ldc_R4: - writer.Write((ushort)instr.OpCode.Code); - writer.Write((float)instr.Operand); - break; - - case Code.Ldc_R8: - writer.Write((ushort)instr.OpCode.Code); - writer.Write((double)instr.Operand); - break; - - case Code.Ldfld: - var typeField = instr.Operand as FieldDef; - bool isField = IsTypeField(typeField); - writer.Write((ushort)instr.OpCode.Code); - writer.Write(isField); - if (isField) { - if (i + 1 < instrs.Count && instrs[i + 1].IsLdcI4()) - i++; - writer.Write(GetFieldId(typeField)); - } - else - Write(writer, instr.Operand); - break; - - case Code.Call: - case Code.Callvirt: - case Code.Newobj: - case Code.Jmp: - case Code.Ldftn: - case Code.Ldvirtftn: - case Code.Ldtoken: - case Code.Stfld: - case Code.Ldsfld: - case Code.Stsfld: - case Code.Ldflda: - case Code.Ldsflda: - case Code.Cpobj: - case Code.Ldobj: - case Code.Castclass: - case Code.Isinst: - case Code.Unbox: - case Code.Stobj: - case Code.Box: - case Code.Newarr: - case Code.Ldelema: - case Code.Ldelem: - case Code.Stelem: - case Code.Unbox_Any: - case Code.Refanyval: - case Code.Mkrefany: - case Code.Initobj: - case Code.Constrained: - case Code.Sizeof: - writer.Write((ushort)instr.OpCode.Code); - Write(writer, instr.Operand); - break; - - case Code.Ldstr: - writer.Write((ushort)instr.OpCode.Code); - break; - - case Code.Ldarg: - case Code.Ldarg_S: - case Code.Ldarg_0: - case Code.Ldarg_1: - case Code.Ldarg_2: - case Code.Ldarg_3: - writer.Write((ushort)Code.Ldarg); - writer.Write(instr.Instruction.GetParameterIndex()); - break; - - case Code.Ldarga: - case Code.Ldarga_S: - writer.Write((ushort)Code.Ldarga); - writer.Write(instr.Instruction.GetParameterIndex()); - break; - - case Code.Starg: - case Code.Starg_S: - writer.Write((ushort)Code.Starg); - writer.Write(instr.Instruction.GetParameterIndex()); - break; - - case Code.Ldloc: - case Code.Ldloc_S: - case Code.Ldloc_0: - case Code.Ldloc_1: - case Code.Ldloc_2: - case Code.Ldloc_3: - writer.Write((ushort)Code.Ldloc); - break; - - case Code.Ldloca: - case Code.Ldloca_S: - writer.Write((ushort)Code.Ldloca); - break; - - case Code.Stloc: - case Code.Stloc_S: - case Code.Stloc_0: - case Code.Stloc_1: - case Code.Stloc_2: - case Code.Stloc_3: - writer.Write((ushort)Code.Stloc); - break; - - case Code.Ldnull: - case Code.Throw: - case Code.Rethrow: - case Code.Ldlen: - case Code.Ckfinite: - case Code.Arglist: - case Code.Localloc: - case Code.Volatile: - case Code.Tailcall: - case Code.Cpblk: - case Code.Initblk: - case Code.Refanytype: - case Code.Readonly: - case Code.Break: - case Code.Endfinally: - case Code.Endfilter: - writer.Write((ushort)instr.OpCode.Code); - break; - - case Code.Calli: - writer.Write((ushort)instr.OpCode.Code); - Write(writer, instr.Operand); - break; - - case Code.Unaligned: - writer.Write((ushort)instr.OpCode.Code); - writer.Write((byte)instr.Operand); - break; - - default: - break; - } - } - } - - void Write(BinaryWriter writer, object op) { - var fd = op as FieldDef; - if (fd != null) { - Write(writer, fd); - return; - } - - var mr = op as MemberRef; - if (mr != null) { - Write(writer, mr); - return; - } - - var md = op as MethodDef; - if (md != null) { - Write(writer, md); - return; - } - - var ms = op as MethodSpec; - if (ms != null) { - Write(writer, ms); - return; - } - - var td = op as TypeDef; - if (td != null) { - Write(writer, td); - return; - } - - var tr = op as TypeRef; - if (tr != null) { - Write(writer, tr); - return; - } - - var ts = op as TypeSpec; - if (ts != null) { - Write(writer, ts); - return; - } - - var fsig = op as FieldSig; - if (fsig != null) { - Write(writer, fsig); - return; - } - - var msig = op as MethodSig; - if (msig != null) { - Write(writer, msig); - return; - } - - var gsig = op as GenericInstMethodSig; - if (gsig != null) { - Write(writer, gsig); - return; - } - - var asmRef = op as AssemblyRef; - if (asmRef != null) { - Write(writer, asmRef); - return; - } - - writer.Write((byte)ObjectType.Unknown); - } - - enum ObjectType : byte { - // 00..3F = Table.XXX values. - Unknown = 0x40, - TypeSig = 0x41, - FieldSig = 0x42, - MethodSig = 0x43, - GenericInstMethodSig = 0x44, - } - - void Write(BinaryWriter writer, TypeSig sig) { - Write(writer, sig, 0); - } - - void Write(BinaryWriter writer, TypeSig sig, int level) { - if (level++ > 20) - return; - - writer.Write((byte)ObjectType.TypeSig); - var etype = sig.GetElementType(); - writer.Write((byte)etype); - switch (etype) { - case ElementType.Ptr: - case ElementType.ByRef: - case ElementType.SZArray: - case ElementType.Pinned: - Write(writer, sig.Next, level); - break; - - case ElementType.Array: - var arySig = (ArraySig)sig; - writer.Write(arySig.Rank); - writer.Write(arySig.Sizes.Count); - writer.Write(arySig.LowerBounds.Count); - Write(writer, sig.Next, level); - break; - - case ElementType.CModReqd: - case ElementType.CModOpt: - Write(writer, ((ModifierSig)sig).Modifier); - Write(writer, sig.Next, level); - break; - - case ElementType.ValueArray: - writer.Write(((ValueArraySig)sig).Size); - Write(writer, sig.Next, level); - break; - - case ElementType.Module: - writer.Write(((ModuleSig)sig).Index); - Write(writer, sig.Next, level); - break; - - case ElementType.GenericInst: - var gis = (GenericInstSig)sig; - Write(writer, gis.GenericType, level); - foreach (var ga in gis.GenericArguments) - Write(writer, ga, level); - Write(writer, sig.Next, level); - break; - - case ElementType.FnPtr: - Write(writer, ((FnPtrSig)sig).Signature); - break; - - case ElementType.Var: - case ElementType.MVar: - writer.Write(((GenericSig)sig).Number); - break; - - case ElementType.ValueType: - case ElementType.Class: - Write(writer, ((TypeDefOrRefSig)sig).TypeDefOrRef); - break; - - case ElementType.End: - case ElementType.Void: - case ElementType.Boolean: - case ElementType.Char: - case ElementType.I1: - case ElementType.U1: - case ElementType.I2: - case ElementType.U2: - case ElementType.I4: - case ElementType.U4: - case ElementType.I8: - case ElementType.U8: - case ElementType.R4: - case ElementType.R8: - case ElementType.String: - case ElementType.TypedByRef: - case ElementType.I: - case ElementType.U: - case ElementType.R: - case ElementType.Object: - case ElementType.Internal: - case ElementType.Sentinel: - default: - break; - } - } - - void Write(BinaryWriter writer, FieldSig sig) { - writer.Write((byte)ObjectType.FieldSig); - writer.Write((byte)(sig == null ? 0 : sig.GetCallingConvention())); - Write(writer, sig.GetFieldType()); - } - - void Write(BinaryWriter writer, MethodSig sig) { - writer.Write((byte)ObjectType.MethodSig); - writer.Write((byte)(sig == null ? 0 : sig.GetCallingConvention())); - Write(writer, sig.GetRetType()); - foreach (var p in sig.GetParams()) - Write(writer, p); - writer.Write(sig.GetParamCount()); - bool hasParamsAfterSentinel = sig.GetParamsAfterSentinel() != null; - writer.Write(hasParamsAfterSentinel); - if (hasParamsAfterSentinel) { - foreach (var p in sig.GetParamsAfterSentinel()) - Write(writer, p); - } - } - - void Write(BinaryWriter writer, GenericInstMethodSig sig) { - writer.Write((byte)ObjectType.GenericInstMethodSig); - writer.Write((byte)(sig == null ? 0 : sig.GetCallingConvention())); - foreach (var ga in sig.GetGenericArguments()) - Write(writer, ga); - } - - void Write(BinaryWriter writer, FieldDef fd) { - writer.Write((byte)Table.Field); - Write(writer, fd.DeclaringType); - var attrMask = FieldAttributes.Static | FieldAttributes.InitOnly | - FieldAttributes.Literal | FieldAttributes.SpecialName | - FieldAttributes.PinvokeImpl | FieldAttributes.RTSpecialName; - writer.Write((ushort)(fd == null ? 0 : fd.Attributes & attrMask)); - Write(writer, fd == null ? null : fd.Signature); - } - - void Write(BinaryWriter writer, MemberRef mr) { - writer.Write((byte)Table.MemberRef); - var parent = mr == null ? null : mr.Class; - Write(writer, parent); - bool canWriteName = IsFromNonObfuscatedAssembly(parent); - writer.Write(canWriteName); - if (canWriteName) - writer.Write(mr.Name); - Write(writer, mr == null ? null : mr.Signature); - } - - void Write(BinaryWriter writer, MethodDef md) { - writer.Write((byte)Table.Method); - Write(writer, md.DeclaringType); - var attrMask1 = MethodImplAttributes.CodeTypeMask | MethodImplAttributes.ManagedMask | - MethodImplAttributes.ForwardRef | MethodImplAttributes.PreserveSig | - MethodImplAttributes.InternalCall; - writer.Write((ushort)(md == null ? 0 : md.ImplAttributes & attrMask1)); - var attrMask2 = MethodAttributes.Static | MethodAttributes.Virtual | - MethodAttributes.HideBySig | MethodAttributes.VtableLayoutMask | - MethodAttributes.CheckAccessOnOverride | MethodAttributes.Abstract | - MethodAttributes.SpecialName | MethodAttributes.PinvokeImpl | - MethodAttributes.UnmanagedExport | MethodAttributes.RTSpecialName; - writer.Write((ushort)(md == null ? 0 : md.Attributes & attrMask2)); - Write(writer, md == null ? null : md.Signature); - writer.Write(md == null ? 0 : md.ParamDefs.Count); - writer.Write(md == null ? 0 : md.GenericParameters.Count); - writer.Write(md == null ? false : md.HasImplMap); - writer.Write(GetId(md)); - } - - void Write(BinaryWriter writer, MethodSpec ms) { - writer.Write((byte)Table.MethodSpec); - Write(writer, ms == null ? null : ms.Method); - Write(writer, ms == null ? null : ms.Instantiation); - } - - void Write(BinaryWriter writer, TypeDef td) { - writer.Write((byte)Table.TypeDef); - Write(writer, td == null ? null : td.BaseType); - var attrMask = TypeAttributes.LayoutMask | TypeAttributes.ClassSemanticsMask | - TypeAttributes.Abstract | TypeAttributes.SpecialName | - TypeAttributes.Import | TypeAttributes.WindowsRuntime | - TypeAttributes.StringFormatMask | TypeAttributes.RTSpecialName; - writer.Write((uint)(td == null ? 0 : td.Attributes & attrMask)); - Write(writer, td == null ? null : td.BaseType); - writer.Write(td == null ? 0 : td.GenericParameters.Count); - writer.Write(td == null ? 0 : td.Interfaces.Count); - if (td != null) { - foreach (var iface in td.Interfaces) - Write(writer, iface); - } - writer.Write(GetId(td)); - } - - void Write(BinaryWriter writer, TypeRef tr) { - writer.Write((byte)Table.TypeRef); - Write(writer, tr == null ? null : tr.ResolutionScope); - bool canWriteName = IsFromNonObfuscatedAssembly(tr); - writer.Write(canWriteName); - if (canWriteName) { - writer.Write(tr.Namespace); - writer.Write(tr.Name); - } - } - - void Write(BinaryWriter writer, TypeSpec ts) { - writer.Write((byte)Table.TypeSpec); - Write(writer, ts == null ? null : ts.TypeSig); - } - - void Write(BinaryWriter writer, AssemblyRef asmRef) { - writer.Write((byte)Table.AssemblyRef); - - bool canWriteAsm = IsNonObfuscatedAssembly(asmRef); - writer.Write(canWriteAsm); - if (canWriteAsm) { - bool hasPk = !PublicKeyBase.IsNullOrEmpty2(asmRef.PublicKeyOrToken); - writer.Write(hasPk); - if (hasPk) - writer.Write(PublicKeyBase.ToPublicKeyToken(asmRef.PublicKeyOrToken).Data); - writer.Write(asmRef.Name); - writer.Write(asmRef.Culture); - } - } - - static bool IsFromNonObfuscatedAssembly(IMemberRefParent mrp) { - return IsFromNonObfuscatedAssembly(mrp as TypeRef); - } - - static bool IsFromNonObfuscatedAssembly(TypeRef tr) { - if (tr == null) - return false; - - for (int i = 0; i < 100; i++) { - var asmRef = tr.ResolutionScope as AssemblyRef; - if (asmRef != null) - return IsNonObfuscatedAssembly(asmRef); - - var tr2 = tr.ResolutionScope as TypeRef; - if (tr2 != null) { - tr = tr2; - continue; - } - - break; - } - - return false; - } - - static bool IsNonObfuscatedAssembly(AssemblyRef asmRef) { - if (asmRef == null) - return false; - // The only external asm refs it uses... - if (asmRef.Name != "mscorlib" && asmRef.Name != "System") - return false; - - return true; - } - - bool IsTypeField(FieldDef fd) { - return fd != null && fd.DeclaringType == blocks.Method.DeclaringType; - } - - int GetFieldId(FieldDef fd) { - if (fd == null) - return int.MinValue; - var fieldType = fd.FieldSig.GetFieldType(); - if (fieldType == null) - return int.MinValue + 1; - - int result = 0; - for (int i = 0; i < 100; i++) { - result += (int)fieldType.ElementType; - if (fieldType.Next == null) - break; - result += 0x100; - fieldType = fieldType.Next; - } - - var td = fieldType.TryGetTypeDef(); - if (td != null && td.IsEnum) - return result + 0x10000000; - return result; - } - - static Code SimplifyBranch(Code code) { - switch (code) { - case Code.Beq_S: return Code.Beq; - case Code.Bge_S: return Code.Bge; - case Code.Bgt_S: return Code.Bgt; - case Code.Ble_S: return Code.Ble; - case Code.Blt_S: return Code.Blt; - case Code.Bne_Un_S: return Code.Bne_Un; - case Code.Bge_Un_S: return Code.Bge_Un; - case Code.Bgt_Un_S: return Code.Bgt_Un; - case Code.Ble_Un_S: return Code.Ble_Un; - case Code.Blt_Un_S: return Code.Blt_Un; - case Code.Br_S: return Code.Br; - case Code.Brfalse_S: return Code.Brfalse; - case Code.Brtrue_S: return Code.Brtrue; - case Code.Leave_S: return Code.Leave; - default: return code; - } - } - } -} diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/OpCodeHandler.cs b/de4dot.code/deobfuscators/Agile_NET/vm/v2/OpCodeHandler.cs deleted file mode 100644 index 606d1f68..00000000 --- a/de4dot.code/deobfuscators/Agile_NET/vm/v2/OpCodeHandler.cs +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright (C) 2011-2013 de4dot@gmail.com - - This file is part of de4dot. - - de4dot is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - de4dot is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with de4dot. If not, see . -*/ - -using dnlib.DotNet; - -namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { - class OpCodeHandler { - public OpCodeHandlerInfo OpCodeHandlerInfo { get; private set; } - public TypeDef HandlerType { get; private set; } - public HandlerMethod ExecMethod { get; private set; } - - public OpCodeHandler(OpCodeHandlerInfo opCodeHandlerInfo, TypeDef handlerType, HandlerMethod execMethod) { - this.OpCodeHandlerInfo = opCodeHandlerInfo; - this.HandlerType = handlerType; - this.ExecMethod = execMethod; - } - - public override string ToString() { - return OpCodeHandlerInfo.Name; - } - } -} diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/OpCodeHandlerInfo.cs b/de4dot.code/deobfuscators/Agile_NET/vm/v2/OpCodeHandlerInfo.cs index d7d3d48d..1d07cf95 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/v2/OpCodeHandlerInfo.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/v2/OpCodeHandlerInfo.cs @@ -19,24 +19,35 @@ using System; using System.Collections.Generic; +using System.Text; namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { class OpCodeHandlerInfo { public HandlerTypeCode TypeCode { get; private set; } public string Name { get; private set; } - public MethodSigInfo ExecSig { get; private set; } - public OpCodeHandlerInfo(HandlerTypeCode typeCode, MethodSigInfo execSig) { + public OpCodeHandlerInfo(HandlerTypeCode typeCode) { this.TypeCode = typeCode; this.Name = GetHandlerName(typeCode); - this.ExecSig = execSig; } public override string ToString() { return Name; } - static string GetHandlerName(HandlerTypeCode code) { + public static string GetCompositeName(IList typeCodes) { + if (typeCodes.Count == 0) + return ""; + var sb = new StringBuilder(); + foreach (var typeCode in typeCodes) { + if (sb.Length != 0) + sb.Append(", "); + sb.Append(GetHandlerName(typeCode)); + } + return sb.ToString(); + } + + public static string GetHandlerName(HandlerTypeCode code) { switch (code) { case HandlerTypeCode.Add: return "add"; case HandlerTypeCode.Add_Ovf: return "add.ovf"; diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/OpCodeHandlerInfos.cs b/de4dot.code/deobfuscators/Agile_NET/vm/v2/OpCodeHandlerInfos.cs index 13165b97..a78753b8 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/v2/OpCodeHandlerInfos.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/v2/OpCodeHandlerInfos.cs @@ -23,75 +23,61 @@ using System.IO; namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { static class OpCodeHandlerInfos { - enum OpCodeHandlersFileVersion : int { - V1 = 1, - } - - public static void Write(BinaryWriter writer, IList handlerInfos) { - WriteV1(writer, handlerInfos); - } - - public static void WriteV1(BinaryWriter writer, IList handlerInfos) { - writer.Write((int)OpCodeHandlersFileVersion.V1); + public static void Write(BinaryWriter writer, List handlerInfos) { + writer.Write(1); writer.Write(handlerInfos.Count); foreach (var handler in handlerInfos) { writer.Write((int)handler.TypeCode); - var infos = handler.ExecSig.BlockInfos; - writer.Write(infos.Count); - foreach (var info in infos) { - if (info.Hash == null) - writer.Write(0); - else { - writer.Write(info.Hash.Length); - writer.Write(info.Hash); - } + writer.Write(handler.BlockSigInfos.Count); + foreach (var info in handler.BlockSigInfos) { writer.Write(info.Targets.Count); foreach (var target in info.Targets) writer.Write(target); + writer.Write(info.Hashes.Count); + foreach (var hash in info.Hashes) + writer.Write((uint)hash); + writer.Write(info.HasFallThrough); + writer.Write(info.EndsInRet); } } } - public static List Read(BinaryReader reader) { - switch ((OpCodeHandlersFileVersion)reader.ReadInt32()) { - case OpCodeHandlersFileVersion.V1: return ReadV1(reader); - default: throw new ApplicationException("Invalid file version"); - } - } - - static List ReadV1(BinaryReader reader) { + public static List Read(BinaryReader reader) { + if (reader.ReadInt32() != 1) + throw new InvalidDataException(); int numHandlers = reader.ReadInt32(); - var list = new List(numHandlers); + var list = new List(numHandlers); for (int i = 0; i < numHandlers; i++) { var typeCode = (HandlerTypeCode)reader.ReadInt32(); - int numInfos = reader.ReadInt32(); - var sigInfo = new MethodSigInfo(); - for (int j = 0; j < numInfos; j++) { - var info = new BlockInfo(); - - info.Hash = reader.ReadBytes(reader.ReadInt32()); - if (info.Hash.Length == 0) - info.Hash = null; - + int numBlocks = reader.ReadInt32(); + var blocks = new List(numBlocks); + for (int j = 0; j < numBlocks; j++) { int numTargets = reader.ReadInt32(); + var targets = new List(numTargets); for (int k = 0; k < numTargets; k++) - info.Targets.Add(reader.ReadInt32()); - - sigInfo.BlockInfos.Add(info); + targets.Add(reader.ReadInt32()); + var numHashes = reader.ReadInt32(); + var hashes = new List(numHashes); + for (int k = 0; k < numHashes; k++) + hashes.Add((BlockElementHash)reader.ReadInt32()); + var block = new BlockSigInfo(hashes, targets); + block.HasFallThrough = reader.ReadBoolean(); + block.EndsInRet = reader.ReadBoolean(); + blocks.Add(block); } - - list.Add(new OpCodeHandlerInfo(typeCode, sigInfo)); + list.Add(new MethodSigInfo(blocks, typeCode)); } return list; } - public static readonly IList[] HandlerInfos = new IList[] { - ReadOpCodeHandlerInfos(CsvmResources.CSVM1_v2), - ReadOpCodeHandlerInfos(CsvmResources.CSVM2_v2), - ReadOpCodeHandlerInfos(CsvmResources.CSVM3_v2), + public static readonly IList[] HandlerInfos = new IList[] { + ReadOpCodeHandlerInfos(CsvmResources.CSVM1), + ReadOpCodeHandlerInfos(CsvmResources.CSVM2), + ReadOpCodeHandlerInfos(CsvmResources.CSVM3), + ReadOpCodeHandlerInfos(CsvmResources.CSVM4), }; - static IList ReadOpCodeHandlerInfos(byte[] data) { + static IList ReadOpCodeHandlerInfos(byte[] data) { return OpCodeHandlerInfos.Read(new BinaryReader(new MemoryStream(data))); } } diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/SigCreator.cs b/de4dot.code/deobfuscators/Agile_NET/vm/v2/SigCreator.cs new file mode 100644 index 00000000..0206b16f --- /dev/null +++ b/de4dot.code/deobfuscators/Agile_NET/vm/v2/SigCreator.cs @@ -0,0 +1,593 @@ +/* + Copyright (C) 2011-2013 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using dnlib.DotNet; +using dnlib.DotNet.Emit; +using de4dot.blocks; + +namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { + class MethodSigInfo { + public HandlerTypeCode TypeCode { get; set; } + public List BlockSigInfos { get; private set; } + + public MethodSigInfo(List blockSigInfos) { + this.BlockSigInfos = blockSigInfos; + } + + public MethodSigInfo(List blockSigInfos, HandlerTypeCode typeCode) { + this.BlockSigInfos = blockSigInfos; + this.TypeCode = typeCode; + } + + public override string ToString() { + return OpCodeHandlerInfo.GetHandlerName(TypeCode); + } + } + + class BlockSigInfo { + readonly List targets; + + public List Hashes { get; private set; } + public List Targets { + get { return targets; } + } + public bool HasFallThrough { get; set; } + public bool EndsInRet { get; set; } + + public BlockSigInfo() { + this.targets = new List(); + this.Hashes = new List(); + } + + public BlockSigInfo(List hashes, List targets) { + this.Hashes = hashes; + this.targets = targets; + } + } + + enum BlockElementHash : int { + } + + class SigCreator { + const int BASE_INDEX = 0x40000000; + Blocks blocks; + Dictionary objToId = new Dictionary(); + CRC32 hasher = new CRC32(); + + public SigCreator() { + } + + public void AddId(object key, int id) { + if (key != null) + objToId[key] = id; + } + + int? GetId(object key) { + if (key == null) + return null; + + int id; + if (objToId.TryGetValue(key, out id)) + return id; + return null; + } + + public List Create(MethodDef method) { + blocks = new Blocks(method); + var allBlocks = blocks.MethodBlocks.GetAllBlocks(); + + var blockInfos = new List(allBlocks.Count); + foreach (var block in allBlocks) { + var blockInfo = new BlockSigInfo(); + blockInfo.HasFallThrough = block.FallThrough != null; + blockInfo.EndsInRet = block.LastInstr.OpCode.Code == Code.Ret; + blockInfos.Add(blockInfo); + var instrs = block.Instructions; + for (int i = 0; i < instrs.Count; i++) { + var info = CalculateHash(instrs, ref i); + if (info != null) + blockInfo.Hashes.Add(info.Value); + } + } + + for (int i = 0; i < blockInfos.Count; i++) { + var block = allBlocks[i]; + var blockInfo = blockInfos[i]; + + if (block.FallThrough != null) + blockInfo.Targets.Add(allBlocks.IndexOf(block.FallThrough)); + if (block.Targets != null) { + foreach (var target in block.Targets) + blockInfo.Targets.Add(allBlocks.IndexOf(target)); + } + } + + return blockInfos; + } + + BlockElementHash? CalculateHash(IList instrs, ref int index) { + hasher.Initialize(); + var instr = instrs[index]; + switch (instr.OpCode.Code) { + case Code.Beq: + case Code.Beq_S: + return GetHash(BASE_INDEX + 0); + + case Code.Bge: + case Code.Bge_S: + return GetHash(BASE_INDEX + 1); + + case Code.Bge_Un: + case Code.Bge_Un_S: + return GetHash(BASE_INDEX + 2); + + case Code.Bgt: + case Code.Bgt_S: + return GetHash(BASE_INDEX + 3); + + case Code.Bgt_Un: + case Code.Bgt_Un_S: + return GetHash(BASE_INDEX + 4); + + case Code.Ble: + case Code.Ble_S: + return GetHash(BASE_INDEX + 5); + + case Code.Ble_Un: + case Code.Ble_Un_S: + return GetHash(BASE_INDEX + 6); + + case Code.Blt: + case Code.Blt_S: + return GetHash(BASE_INDEX + 7); + + case Code.Blt_Un: + case Code.Blt_Un_S: + return GetHash(BASE_INDEX + 8); + + case Code.Bne_Un: + case Code.Bne_Un_S: + return GetHash(BASE_INDEX + 9); + + case Code.Brfalse: + case Code.Brfalse_S: + return GetHash(BASE_INDEX + 10); + + case Code.Brtrue: + case Code.Brtrue_S: + return GetHash(BASE_INDEX + 11); + + case Code.Switch: + return GetHash(BASE_INDEX + 12); + + case Code.Ceq: + return GetHash(BASE_INDEX + 13); + + case Code.Cgt: + return GetHash(BASE_INDEX + 14); + + case Code.Cgt_Un: + return GetHash(BASE_INDEX + 15); + + case Code.Clt: + return GetHash(BASE_INDEX + 16); + + case Code.Clt_Un: + return GetHash(BASE_INDEX + 17); + + case Code.Ldc_I4: + case Code.Ldc_I4_0: + case Code.Ldc_I4_1: + case Code.Ldc_I4_2: + case Code.Ldc_I4_3: + case Code.Ldc_I4_4: + case Code.Ldc_I4_5: + case Code.Ldc_I4_6: + case Code.Ldc_I4_7: + case Code.Ldc_I4_8: + case Code.Ldc_I4_M1: + case Code.Ldc_I4_S: + return GetHash(instr.GetLdcI4Value()); + + case Code.Ldstr: + return GetHash(instr.Operand as string); + + case Code.Rethrow: + return GetHash(BASE_INDEX + 18); + + case Code.Throw: + return GetHash(BASE_INDEX + 19); + + case Code.Call: + case Code.Callvirt: + Hash(instr.Operand); + return (BlockElementHash)hasher.GetHash(); + + case Code.Ldfld: + var field = instr.Operand as FieldDef; + if (!IsTypeField(field)) + return null; + if (index + 1 >= instrs.Count || !instrs[index + 1].IsLdcI4()) + return null; + index++; + return GetHash(GetFieldId(field)); + + default: + break; + } + return null; + } + + bool IsTypeField(FieldDef fd) { + return fd != null && fd.DeclaringType == blocks.Method.DeclaringType; + } + + static int GetFieldId(FieldDef fd) { + if (fd == null) + return int.MinValue; + var fieldType = fd.FieldSig.GetFieldType(); + if (fieldType == null) + return int.MinValue + 1; + + int result = BASE_INDEX + 0x1000; + for (int i = 0; i < 100; i++) { + result += (int)fieldType.ElementType; + if (fieldType.Next == null) + break; + result += 0x100; + fieldType = fieldType.Next; + } + + var td = fieldType.TryGetTypeDef(); + if (td != null && td.IsEnum) + return result + 0x10000000; + return result; + } + + void Hash(object op) { + var md = op as MethodDef; + if (md != null) { + Hash(md); + return; + } + + var mr = op as MemberRef; + if (mr != null) { + Hash(mr); + return; + } + + var td = op as TypeDef; + if (td != null) { + Hash(td); + return; + } + + var tr = op as TypeRef; + if (tr != null) { + Hash(tr); + return; + } + + var ts = op as TypeSpec; + if (ts != null) { + Hash(ts); + return; + } + + var fsig = op as FieldSig; + if (fsig != null) { + Hash(fsig); + return; + } + + var msig = op as MethodSig; + if (msig != null) { + Hash(msig); + return; + } + + var gsig = op as GenericInstMethodSig; + if (gsig != null) { + Hash(gsig); + return; + } + + var asmRef = op as AssemblyRef; + if (asmRef != null) { + Hash(asmRef); + return; + } + + var tsig = op as TypeSig; + if (tsig != null) { + Hash(tsig); + return; + } + + return; + } + + void Hash(TypeSig sig) { + Hash(sig, 0); + } + + void Hash(TypeSig sig, int level) { + if (sig == null) + return; + if (level++ > 20) + return; + + hasher.Hash((byte)0x41); + var etype = sig.GetElementType(); + hasher.Hash((byte)etype); + switch (etype) { + case ElementType.Ptr: + case ElementType.ByRef: + case ElementType.SZArray: + case ElementType.Pinned: + Hash(sig.Next, level); + break; + + case ElementType.Array: + var arySig = (ArraySig)sig; + hasher.Hash(arySig.Rank); + hasher.Hash(arySig.Sizes.Count); + hasher.Hash(arySig.LowerBounds.Count); + Hash(sig.Next, level); + break; + + case ElementType.CModReqd: + case ElementType.CModOpt: + Hash(((ModifierSig)sig).Modifier); + Hash(sig.Next, level); + break; + + case ElementType.ValueArray: + hasher.Hash(((ValueArraySig)sig).Size); + Hash(sig.Next, level); + break; + + case ElementType.Module: + hasher.Hash(((ModuleSig)sig).Index); + Hash(sig.Next, level); + break; + + case ElementType.GenericInst: + var gis = (GenericInstSig)sig; + Hash(gis.GenericType, level); + foreach (var ga in gis.GenericArguments) + Hash(ga, level); + Hash(sig.Next, level); + break; + + case ElementType.FnPtr: + Hash(((FnPtrSig)sig).Signature); + break; + + case ElementType.Var: + case ElementType.MVar: + hasher.Hash(((GenericSig)sig).Number); + break; + + case ElementType.ValueType: + case ElementType.Class: + Hash(((TypeDefOrRefSig)sig).TypeDefOrRef); + break; + + case ElementType.End: + case ElementType.Void: + case ElementType.Boolean: + case ElementType.Char: + case ElementType.I1: + case ElementType.U1: + case ElementType.I2: + case ElementType.U2: + case ElementType.I4: + case ElementType.U4: + case ElementType.I8: + case ElementType.U8: + case ElementType.R4: + case ElementType.R8: + case ElementType.String: + case ElementType.TypedByRef: + case ElementType.I: + case ElementType.U: + case ElementType.R: + case ElementType.Object: + case ElementType.Internal: + case ElementType.Sentinel: + default: + break; + } + } + + void Hash(MethodDef md) { + if (md == null) + return; + + var attrMask1 = MethodImplAttributes.CodeTypeMask | MethodImplAttributes.ManagedMask | + MethodImplAttributes.ForwardRef | MethodImplAttributes.PreserveSig | + MethodImplAttributes.InternalCall; + hasher.Hash((ushort)(md == null ? 0 : md.ImplAttributes & attrMask1)); + var attrMask2 = MethodAttributes.Static | MethodAttributes.Virtual | + MethodAttributes.HideBySig | MethodAttributes.VtableLayoutMask | + MethodAttributes.CheckAccessOnOverride | MethodAttributes.Abstract | + MethodAttributes.SpecialName | MethodAttributes.PinvokeImpl | + MethodAttributes.UnmanagedExport | MethodAttributes.RTSpecialName; + hasher.Hash((ushort)(md.Attributes & attrMask2)); + Hash(md.Signature); + hasher.Hash(md.ParamDefs.Count); + hasher.Hash(md.GenericParameters.Count); + hasher.Hash(md.HasImplMap ? 1 : 0); + + var id = GetId(md); + if (id != null) + hasher.Hash(id.Value); + } + + void Hash(MemberRef mr) { + if (mr == null) + return; + + Hash(mr.Class); + if (IsFromNonObfuscatedAssembly(mr.Class)) + Hash(mr.Name); + Hash(mr.Signature); + } + + void Hash(TypeDef td) { + if (td == null) + return; + + Hash(td.BaseType); + var attrMask = TypeAttributes.LayoutMask | TypeAttributes.ClassSemanticsMask | + TypeAttributes.Abstract | TypeAttributes.SpecialName | + TypeAttributes.Import | TypeAttributes.WindowsRuntime | + TypeAttributes.StringFormatMask | TypeAttributes.RTSpecialName; + hasher.Hash((uint)(td.Attributes & attrMask)); + hasher.Hash(td.GenericParameters.Count); + hasher.Hash(td.Interfaces.Count); + foreach (var iface in td.Interfaces) + Hash(iface.Interface); + var id = GetId(td); + if (id != null) + hasher.Hash(id.Value); + } + + void Hash(TypeRef tr) { + if (tr == null) + return; + + Hash(tr.ResolutionScope); + if (IsFromNonObfuscatedAssembly(tr)) { + Hash(tr.Namespace); + Hash(tr.Name); + } + } + + void Hash(TypeSpec ts) { + if (ts == null) + return; + + Hash(ts.TypeSig); + } + + void Hash(FieldSig sig) { + if (sig == null) + return; + + hasher.Hash((byte)sig.GetCallingConvention()); + Hash(sig.GetFieldType()); + } + + void Hash(MethodSig sig) { + if (sig == null) + return; + + hasher.Hash((byte)sig.GetCallingConvention()); + Hash(sig.GetRetType()); + foreach (var p in sig.GetParams()) + Hash(p); + hasher.Hash(sig.GetParamCount()); + if (sig.GetParamsAfterSentinel() != null) { + foreach (var p in sig.GetParamsAfterSentinel()) + Hash(p); + } + } + + void Hash(GenericInstMethodSig sig) { + if (sig == null) + return; + + hasher.Hash((byte)sig.GetCallingConvention()); + foreach (var ga in sig.GetGenericArguments()) + Hash(ga); + } + + void Hash(AssemblyRef asmRef) { + if (asmRef == null) + return; + + bool canWriteAsm = IsNonObfuscatedAssembly(asmRef); + hasher.Hash(canWriteAsm ? 1 : 0); + if (canWriteAsm) { + bool hasPk = !PublicKeyBase.IsNullOrEmpty2(asmRef.PublicKeyOrToken); + if (hasPk) + hasher.Hash(PublicKeyBase.ToPublicKeyToken(asmRef.PublicKeyOrToken).Data); + Hash(asmRef.Name); + Hash(asmRef.Culture); + } + } + + void Hash(string s) { + if (s != null) + hasher.Hash(Encoding.UTF8.GetBytes(s)); + } + + BlockElementHash GetHash(int val) { + hasher.Hash(val); + return (BlockElementHash)hasher.GetHash(); + } + + BlockElementHash GetHash(string s) { + Hash(s); + return (BlockElementHash)hasher.GetHash(); + } + + static bool IsFromNonObfuscatedAssembly(IMemberRefParent mrp) { + return IsFromNonObfuscatedAssembly(mrp as TypeRef); + } + + static bool IsFromNonObfuscatedAssembly(TypeRef tr) { + if (tr == null) + return false; + + for (int i = 0; i < 100; i++) { + var asmRef = tr.ResolutionScope as AssemblyRef; + if (asmRef != null) + return IsNonObfuscatedAssembly(asmRef); + + var tr2 = tr.ResolutionScope as TypeRef; + if (tr2 != null) { + tr = tr2; + continue; + } + + break; + } + + return false; + } + + static bool IsNonObfuscatedAssembly(IAssembly asm) { + if (asm == null) + return false; + + // The only external asm refs it uses... + if (asm.Name != "mscorlib" && asm.Name != "System") + return false; + + return true; + } + } +} diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/VmOpCode.cs b/de4dot.code/deobfuscators/Agile_NET/vm/v2/VmOpCode.cs index bb1fdd85..10bc1beb 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/v2/VmOpCode.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/v2/VmOpCode.cs @@ -22,23 +22,15 @@ using System.Text; namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { class VmOpCode { - public List OpCodeHandlerInfos { get; private set; } + public List HandlerTypeCodes { get; private set; } - public VmOpCode(List opCodeHandlerInfos) { - this.OpCodeHandlerInfos = new List(opCodeHandlerInfos.Count); - this.OpCodeHandlerInfos.AddRange(opCodeHandlerInfos); + public VmOpCode(List opCodeHandlerInfos) { + this.HandlerTypeCodes = new List(opCodeHandlerInfos.Count); + this.HandlerTypeCodes.AddRange(opCodeHandlerInfos); } public override string ToString() { - if (OpCodeHandlerInfos.Count == 0) - return ""; - var sb = new StringBuilder(); - foreach (var handler in OpCodeHandlerInfos) { - if (sb.Length != 0) - sb.Append(", "); - sb.Append(handler.Name); - } - return sb.ToString(); + return OpCodeHandlerInfo.GetCompositeName(HandlerTypeCodes); } } } diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/VmOpCodeHandlerDetector.cs b/de4dot.code/deobfuscators/Agile_NET/vm/v2/VmOpCodeHandlerDetector.cs index ea234c72..c5e56d55 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/v2/VmOpCodeHandlerDetector.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/v2/VmOpCodeHandlerDetector.cs @@ -81,7 +81,6 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { return; deobfuscator = new MyDeobfuscator(module); - var csvmInfo = new CsvmInfo(module); csvmInfo.Initialize(); var vmHandlerTypes = FindVmHandlerTypes(); @@ -90,9 +89,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { var composites = CreateCompositeOpCodeHandlers(csvmInfo, vmHandlerTypes); foreach (var handlerInfos in OpCodeHandlerInfos.HandlerInfos) { - var otherHandlers = CreateOtherHandlers(csvmInfo, handlerInfos); - - if (!DetectCompositeHandlers(composites, otherHandlers)) + if (!DetectCompositeHandlers(composites, handlerInfos)) continue; vmOpCodes = CreateVmOpCodes(composites); @@ -105,12 +102,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { static List CreateVmOpCodes(IList composites) { var list = new List(composites.Count); foreach (var composite in composites) - list.Add(new VmOpCode(composite.OpCodeHandlerInfos)); + list.Add(new VmOpCode(composite.TypeCodes)); return list; } - bool DetectCompositeHandlers(IEnumerable composites, List otherHandlers) { - var detector = new CompositeHandlerDetector(otherHandlers); + bool DetectCompositeHandlers(IEnumerable composites, IList handlerInfos) { + var detector = new CompositeHandlerDetector(handlerInfos); foreach (var composite in composites) { if (!detector.FindHandlers(composite)) return false; @@ -128,15 +125,18 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { List CreateCompositeOpCodeHandlers(CsvmInfo csvmInfo, List handlers) { var list = new List(handlers.Count); - foreach (var handler in handlers) { - var execHandler = new HandlerMethod(GetExecMethod(handler)); - list.Add(new CompositeOpCodeHandler(handler, execHandler)); - } + var sigCreator = CreateSigCreator(csvmInfo); + foreach (var handler in handlers) + list.Add(new CompositeOpCodeHandler(sigCreator.Create(GetExecMethod(handler)))); return list; } MethodDef GetExecMethod(TypeDef type) { + return GetExecMethod(deobfuscator, type); + } + + static MethodDef GetExecMethod(MyDeobfuscator deobfuscator, TypeDef type) { MethodDef readMethod, execMethod; GetReadAndExecMethods(type, out readMethod, out execMethod); deobfuscator.Deobfuscate(execMethod); @@ -144,8 +144,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { return execMethod; } - static MethodSigInfoCreator CreateMethodSigInfoCreator(CsvmInfo csvmInfo) { - var creator = new MethodSigInfoCreator(); + static SigCreator CreateSigCreator(CsvmInfo csvmInfo) { + var creator = new SigCreator(); creator.AddId(csvmInfo.LogicalOpShrUn, 1); creator.AddId(csvmInfo.LogicalOpShl, 2); @@ -183,9 +183,20 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { creator.AddId(csvmInfo.LocalsGet, 30); creator.AddId(csvmInfo.LocalsSet, 31); + AddTypeId(creator, csvmInfo.LogicalOpShrUn, 32); + AddTypeId(creator, csvmInfo.CompareLt, 33); + AddTypeId(creator, csvmInfo.ArithmeticSubOvfUn, 34); + AddTypeId(creator, csvmInfo.UnaryNot, 35); + AddTypeId(creator, csvmInfo.ArgsGet, 36); + return creator; } + static void AddTypeId(SigCreator creator, MethodDef method, int id) { + if (method != null) + creator.AddId(method.DeclaringType, id); + } + static void GetReadAndExecMethods(TypeDef handler, out MethodDef readMethod, out MethodDef execMethod) { readMethod = execMethod = null; foreach (var method in handler.Methods) { @@ -270,28 +281,5 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { return list; } - - List CreateOtherHandlers(CsvmInfo csvmInfo, IList handlerInfos) { - var list = new List(NUM_HANDLERS); - - foreach (var type in GetVmHandlerTypes(csvmInfo.VmHandlerBaseType)) { - if (list.Count == NUM_HANDLERS) - break; - - var execHandler = new PrimitiveHandlerMethod(GetExecMethod(type)); - execHandler.Sig = CreateMethodSigInfoCreator(csvmInfo).Create(execHandler.Blocks); - - var finder = new MethodFinder(handlerInfos, execHandler); - var handler = finder.FindHandler(); - if (handler == null) - continue; - - list.Add(handler); - } - - list.Sort((a, b) => a.OpCodeHandlerInfo.Name.ToUpperInvariant().CompareTo(b.OpCodeHandlerInfo.Name.ToUpperInvariant())); - - return list; - } } } diff --git a/de4dot.mdecrypt/DynamicMethodsDecrypter.cs b/de4dot.mdecrypt/DynamicMethodsDecrypter.cs index 9d40208c..8e41c1b6 100644 --- a/de4dot.mdecrypt/DynamicMethodsDecrypter.cs +++ b/de4dot.mdecrypt/DynamicMethodsDecrypter.cs @@ -581,6 +581,23 @@ namespace de4dot.mdecrypt { return hModule; } + class PatchInfo { + public int RVA; + public byte[] Data; + public byte[] Orig; + + public PatchInfo(int rva, byte[] data, byte[] orig) { + this.RVA = rva; + this.Data = data; + this.Orig = orig; + } + } + static readonly PatchInfo[] patches = new PatchInfo[] { + new PatchInfo(0x000110A5, new byte[] { 0x33, 0xC0, 0xC2, 0x04, 0x00 }, new byte[] { 0xE9, 0x36, 0x3A, 0x00, 0x00 }), + new PatchInfo(0x000110AF, new byte[] { 0x33, 0xC0, 0xC2, 0x04, 0x00 }, new byte[] { 0xE9, 0x4C, 0x3C, 0x00, 0x00 }), + new PatchInfo(0x000110AA, new byte[] { 0x33, 0xC0, 0xC2, 0x04, 0x00 }, new byte[] { 0xE9, 0xF1, 0x3A, 0x00, 0x00 }), + }; + static unsafe bool PatchCM(IntPtr addr, IntPtr origValue, IntPtr newValue) { var baseAddr = GetModuleHandle(addr); IntPtr patchAddr; @@ -590,6 +607,45 @@ namespace de4dot.mdecrypt { return false; *(IntPtr*)patchAddr = newValue; + PatchRT(baseAddr); + return true; + } + + [HandleProcessCorruptedStateExceptions, SecurityCritical] // Req'd on .NET 4.0 + static unsafe bool PatchRT(IntPtr baseAddr) { + foreach (var info in patches) { + try { + var addr = new IntPtr(baseAddr.ToInt64() + info.RVA); + + var data = new byte[info.Orig.Length]; + Marshal.Copy(addr, data, 0, data.Length); + if (!Equals(data, info.Orig)) + continue; + + uint oldProtect; + if (!VirtualProtect(addr, info.Data.Length, PAGE_EXECUTE_READWRITE, out oldProtect)) + throw new ApplicationException("Could not enable write access"); + Marshal.Copy(info.Data, 0, addr, info.Data.Length); + VirtualProtect(addr, info.Data.Length, oldProtect, out oldProtect); + return true; + } + catch { + } + } + return false; + } + + static bool Equals(byte[] a, byte[] b) { + if (a == b) + return true; + if (a == null || b == null) + return false; + if (a.Length != b.Length) + return false; + for (int i = 0; i < a.Length; i++) { + if (a[i] != b[i]) + return false; + } return true; }