[{"data":1,"prerenderedAt":999},["ShallowReactive",2],{"post-barista":3,"post-list":732},{"id":4,"title":5,"alsoIn":6,"body":8,"category":704,"date":705,"description":706,"draft":707,"extension":708,"image":709,"links":710,"meta":718,"navigation":719,"order":720,"path":721,"readingTime":300,"seo":722,"series":723,"stem":724,"strength":725,"tags":726,"unlisted":707,"updated":723,"__hash__":731},"posts\u002Fposts\u002Fbarista.md","Barista: One Exe to Install Doppio and Ristretto",[7],"windows",{"type":9,"value":10,"toc":695},"minimark",[11,31,39,42,58,63,82,119,122,130,144,148,155,158,165,171,316,319,323,334,349,352,363,367,370,376,379,382,415,426,429,487,498,513,517,520,526,530,533,567,574,604,608,634,637,670,676,679,688,691],[12,13,14,15,20,21,25,26,30],"p",{},"At the end of the 2FA series you have three things. A credential provider with a TOTP tile from ",[16,17,19],"a",{"href":18},"\u002Fp\u002Fwindows-2fa-credential-provider\u002F","Part 1",". An authentication package and an MSV1_0 sub-authentication filter inside LSA from ",[16,22,24],{"href":23},"\u002Fp\u002Fwindows-2fa-inside-lsa\u002F","Part 2",". And Ristretto from ",[16,27,29],{"href":28},"\u002Fp\u002Fwindows-2fa-gating-network-logons\u002F","Part 3",", a gate that lets network logons through for a few minutes after you type a one-time code.",[12,32,33,34,38],{},"What you don't have is an easy way to put all of that on a machine. You need the MSVC build tools, two repositories at matching commits, ",[35,36,37],"code",{},"RunAsPPL"," switched off, an unsigned DLL copied into System32, an enrollment per account, a reindex, and a handful of registry writes that have to happen in a certain order. Get the order wrong and the machine doesn't come back after the reboot. I wrote that in Part 2 and I still mean it: change one thing per reboot.",[12,40,41],{},"That's a lot of steps for something you mostly want to try out on a test VM. So I built a wizard for it. It's called Barista, because it makes the Doppio and the Ristretto.",[43,44,45,51],"blockquote",{},[12,46,47],{},[48,49,50],"span",{},"!CAUTION",[12,52,53,54,57],{},"Barista installs code that runs inside ",[35,55,56],{},"lsass.exe",". A fault there is a bluescreen on the logon path, and that can leave a machine that won't boot. Test VMs only, and take a snapshot before every reboot.",[59,60,62],"h2",{"id":61},"what-it-is","What it is",[12,64,65,66,69,70,76,77,81],{},"One file, ",[35,67,68],{},"Barista.exe",". Download it from the ",[16,71,75],{"href":72,"rel":73},"https:\u002F\u002Fgithub.com\u002FNobrac\u002FBarista\u002Freleases\u002Ftag\u002Fv0.1.1",[74],"nofollow","release page",", check its hash, right-click, ",[78,79,80],"em",{},"Run as administrator",". On the machine you need administrator rights. You don't need git, .NET, a compiler or a network connection, because everything Barista installs is already inside the exe.",[83,84,89],"pre",{"className":85,"code":86,"language":87,"meta":88,"style":88},"language-powershell shiki shiki-themes gruvbox-dark-medium","certutil -hashfile Barista.exe SHA256\n# must match the Barista.exe line in SHA256SUMS\n","powershell","",[35,90,91,112],{"__ignoreMap":88},[48,92,95,99,103,106,109],{"class":93,"line":94},"line",1,[48,96,98],{"class":97},"sM0OT","certutil ",[48,100,102],{"class":101},"sM2RB","-",[48,104,105],{"class":97},"hashfile ",[48,107,68],{"class":108},"s59W0",[48,110,111],{"class":97}," SHA256\n",[48,113,115],{"class":93,"line":114},2,[48,116,118],{"class":117},"s-UKz","# must match the Barista.exe line in SHA256SUMS\n",[12,120,121],{},"Inside is a WPF wizard in C# and everything it installs, already compiled. The pages go in this order:",[83,123,128],{"className":124,"code":126,"language":127,"meta":88},[125],"language-text","Risks -> Integrity -> Components -> Preflight -> Accounts -> Install -> Done\n","text",[35,129,126],{"__ignoreMap":88},[12,131,132,133,136,137,139,140,143],{},"Barista itself writes almost nothing to the machine. Every registry key, every copy into System32 and every LSA registration happens in Doppio's and Ristretto's own ",[35,134,135],{},"install-*.ps1"," scripts, the same ones the blog posts walk through. Barista finds them, explains what each one does, runs them in order and shows you the output. Those scripts carry the guards: the ",[35,138,37],{}," check, \"Auth0 already belongs to somebody else\", the ",[35,141,142],{},"PrevAuth0"," bookkeeping, the DLL on disk before the registry names it. A second copy of that logic in C# would drift from the original sooner or later, and then you'd have two install paths that disagree about what's safe.",[59,145,147],{"id":146},"where-the-binaries-come-from","Where the binaries come from",[12,149,150,151,154],{},"The obvious way to build a setup tool for code from GitHub is to have it download and build that code on the target machine. The first versions of Barista did that: a ",[35,152,153],{},"bootstrap.bat"," that installed git, the .NET SDK and the MSVC build tools through winget, cloned both repositories and built them.",[12,156,157],{},"It worked, but it built whatever the default branch was on that day. Nothing checked a commit, a hash or a signature. Anyone who took over the GitHub account or pushed a bad commit would have had code in lsass on every machine that ran the bootstrap afterwards. And the same bootstrap built different software on two different days without telling you. So now CI builds everything, and the exe brings it along.",[12,159,160],{},[161,162],"img",{"alt":163,"src":164},"The release path. payload.lock.json pins Doppio and Ristretto to full commit ids. A tag v* starts the release workflow on GitHub Actions. It checks out both repositories at those commits, compiles them with MSVC, writes payload-manifest.json with the SHA-256 of all 17 files, runs the tests and publishes one self-contained Barista.exe with the payload embedded. The result is a draft release that a person checks and publishes. On the test VM, the Integrity page unpacks the files into a folder only administrators can write to, reads each one back from disk and compares it to the manifest. Continue stays off unless all 17 match, and the check runs again after every reboot and before every stage.","\u002Fimages\u002Fposts\u002Fbarista\u002Frelease-path.svg",[12,166,167,170],{},[35,168,169],{},"payload.lock.json"," in the repository names the exact commits:",[83,172,176],{"className":173,"code":174,"language":175,"meta":88,"style":88},"language-json shiki shiki-themes gruvbox-dark-medium","{\n  \"doppio\": {\n    \"commit\": \"d61192f9e9a2432ab317b0e579a4894e657707f6\"\n  },\n  \"ristretto\": {\n    \"commit\": \"069fb230960565993b8fd48f386095817d3a0524\",\n    \"doppioSubmodule\": {\n      \"commit\": \"d61192f9e9a2432ab317b0e579a4894e657707f6\"\n    }\n  }\n}\n","json",[35,177,178,184,202,225,231,245,266,280,298,304,310],{"__ignoreMap":88},[48,179,180],{"class":93,"line":94},[48,181,183],{"class":182},"svnLg","{\n",[48,185,186,189,193,196,199],{"class":93,"line":114},[48,187,188],{"class":182},"  \"",[48,190,192],{"class":191},"sgVRN","doppio",[48,194,195],{"class":182},"\"",[48,197,198],{"class":182},":",[48,200,201],{"class":182}," {\n",[48,203,205,208,211,213,215,218,222],{"class":93,"line":204},3,[48,206,207],{"class":182},"    \"",[48,209,210],{"class":191},"commit",[48,212,195],{"class":182},[48,214,198],{"class":182},[48,216,217],{"class":182}," \"",[48,219,221],{"class":220},"sMWUE","d61192f9e9a2432ab317b0e579a4894e657707f6",[48,223,224],{"class":182},"\"\n",[48,226,228],{"class":93,"line":227},4,[48,229,230],{"class":182},"  },\n",[48,232,234,236,239,241,243],{"class":93,"line":233},5,[48,235,188],{"class":182},[48,237,238],{"class":191},"ristretto",[48,240,195],{"class":182},[48,242,198],{"class":182},[48,244,201],{"class":182},[48,246,248,250,252,254,256,258,261,263],{"class":93,"line":247},6,[48,249,207],{"class":182},[48,251,210],{"class":191},[48,253,195],{"class":182},[48,255,198],{"class":182},[48,257,217],{"class":182},[48,259,260],{"class":220},"069fb230960565993b8fd48f386095817d3a0524",[48,262,195],{"class":182},[48,264,265],{"class":182},",\n",[48,267,269,271,274,276,278],{"class":93,"line":268},7,[48,270,207],{"class":182},[48,272,273],{"class":191},"doppioSubmodule",[48,275,195],{"class":182},[48,277,198],{"class":182},[48,279,201],{"class":182},[48,281,283,286,288,290,292,294,296],{"class":93,"line":282},8,[48,284,285],{"class":182},"      \"",[48,287,210],{"class":191},[48,289,195],{"class":182},[48,291,198],{"class":182},[48,293,217],{"class":182},[48,295,221],{"class":220},[48,297,224],{"class":182},[48,299,301],{"class":93,"line":300},9,[48,302,303],{"class":182},"    }\n",[48,305,307],{"class":93,"line":306},10,[48,308,309],{"class":182},"  }\n",[48,311,313],{"class":93,"line":312},11,[48,314,315],{"class":182},"}\n",[12,317,318],{},"When I push a tag, GitHub Actions checks out Doppio and Ristretto at those commits, compiles them with MSVC and embeds the result in the exe together with a manifest that lists the SHA-256 of every file. The build script refuses to run if a checkout isn't at its pin or has local changes. The workflow ends with a draft release, so nothing goes public until I've looked at it. To move to newer Doppio or Ristretto commits, I change the pins and tag again.",[59,320,322],{"id":321},"seventeen-hashes-before-continue","Seventeen hashes before Continue",[12,324,325,326,329,330,333],{},"The first page after the risk checkboxes is called ",[78,327,328],{},"Integrity",". It unpacks the 17 embedded files into ",[35,331,332],{},"%ProgramFiles%\\TheAdminCafe\\Barista\\payload",", a folder only administrators and SYSTEM can write to. Then it reads every file back from disk and compares its hash with the manifest.",[12,335,336,337,340,341,344,345,348],{},"You get one line per file with the expected hash above the one on disk, and a big result at the top. Continue stays greyed out unless all 17 match. ",[78,338,339],{},"Copy report"," puts the hashes on the clipboard in ",[35,342,343],{},"sha256sum"," format, so you can compare them with the ",[35,346,347],{},"payload-manifest.json"," on the release page yourself.",[12,350,351],{},"The check runs again after every reboot and before every stage, because the stages are spread over several reboots, and in between something else running as admin could replace a file. After a reboot Barista also ignores the paths in its own state file and uses the payload folder it just verified.",[12,353,354,355,358,359,362],{},"The manifest proves the files on disk are the ones CI built from the pinned commits. It doesn't prove the exe itself is the one I published. That's what ",[35,356,357],{},"SHA256SUMS"," on the release page is for, and in the long run a code signature. The Integrity page shows the exe's own hash and signature status next to the payload, and right now it says ",[78,360,361],{},"unsigned",".",[59,364,366],{"id":365},"one-change-per-reboot","One change per reboot",[12,368,369],{},"I built Barista mainly for this part. The install runs in stages, and every stage that touches something LSA or LogonUI reads at boot ends with a reboot and a question.",[12,371,372],{},[161,373],{"alt":374,"src":375},"The five install stages. Stage 1 installs the credential provider, then a restart and the question whether the tile appears next to the usual ones. Stage 2 enrolls the accounts and rebuilds the RID index, without a restart. Stage 3 registers the provider filter, then a restart and the question whether you can still get in with only the tile. Stage 4 closes the network paths, either with deny rights and no restart, or with Doppio's TacSubAuth or the Ristretto gate in lsass, then a restart and the question whether the machine came back and you can still log on. Stage 5 registers the authentication package, then a restart and the question whether the machine came back. A no after any restart stops the run, names what the last stage changed and offers the matching uninstall script.","\u002Fimages\u002Fposts\u002Fbarista\u002Fstages.svg",[12,377,378],{},"After each restart Barista opens again on its own and asks whether the machine is healthy before it runs anything else. If you answer no, it stops, tells you what the last stage changed and offers the uninstall script that matches. Because there's only ever one new thing on the machine, you know which one it was.",[12,380,381],{},"Each position in that order has a reason:",[383,384,385,393,403,409],"ul",{},[386,387,388,392],"li",{},[389,390,391],"strong",{},"The tile goes first."," It runs in LogonUI, not in lsass, and it's the one stage you can still undo from Safe Mode.",[386,394,395,398,399,402],{},[389,396,397],{},"Enrollment comes before any filter."," The filter judges accounts by whether they have a secret, so they need one first. And ",[35,400,401],{},"enroll \u002Freindex"," has to run before anything reads the RID index.",[386,404,405,408],{},[389,406,407],{},"The provider filter comes before the network stages."," This is the step that removes the password tile. While the network paths are still open, a broken tile still leaves you a way in over SMB or WinRM. The other way round, one bad tile means no way in at all, which is the locked machine from Part 1.",[386,410,411,414],{},[389,412,413],{},"The authentication package is last,"," because it closes nothing.",[12,416,417,418,421,422,425],{},"Stages 1 and 3 are two runs of the same ",[35,419,420],{},"install-doppio.ps1",", once without and once with ",[35,423,424],{},"-EnableFilter",". Before stage 3 Barista asks whether you've signed in through the tile yet. No registry read can tell, and it's the last moment the password tile can still get you in.",[12,427,428],{},"Stage 4 is where you pick how the network paths get closed, and there are three answers:",[430,431,432,448],"table",{},[433,434,435],"thead",{},[436,437,438,442,445],"tr",{},[439,440,441],"th",{},"Choice",[439,443,444],{},"What it does",[439,446,447],{},"Code in lsass",[449,450,451,466,477],"tbody",{},[436,452,453,457,463],{},[454,455,456],"td",{},"Deny rights",[454,458,459,462],{},[35,460,461],{},"deny-noninteractive.ps1"," sets the network, batch and service deny rights per account",[454,464,465],{},"none, no reboot",[436,467,468,471,474],{},[454,469,470],{},"Doppio's TacSubAuth",[454,472,473],{},"refuses every network logon for an enrolled account, RDP with NLA included",[454,475,476],{},"yes, own reboot",[436,478,479,482,485],{},[454,480,481],{},"The Ristretto gate",[454,483,484],{},"network logons work for a few minutes after a one-time code",[454,486,476],{},[12,488,489,490,493,494,497],{},"Deny rights are the supported way and the one I'd start with. The two filters are the interesting ones from Part 2 and Part 3, and for those the question after the reboot comes with a test. For Ristretto: open a gate with ",[35,491,492],{},"ristretto \u003Cuser>",", check that a share works, then ",[35,495,496],{},"ristretto \u002Fclose \u003Cuser>"," and check that it stops working. If it keeps working with the gate closed, MSV1_0 isn't calling the filter on that build and the gate is decorative. You want to find that out while the filter is the only new thing on the machine.",[12,499,500,501,504,505,508,509,512],{},"Between reboots Barista keeps a small record in ",[35,502,503],{},"%ProgramData%\\TheAdminCafe\\Barista\\pending-run.json"," with the finished stages and the log so far, and a ",[35,506,507],{},"RunOnce"," value that opens the wizard after the next logon. The record holds no secrets, those stay DPAPI-encrypted in Doppio's own store. Barista writes it after every finished stage, including the ones without a reboot, so closing the window at the wrong moment can't run ",[35,510,511],{},"enroll.exe"," twice for the same account.",[59,514,516],{"id":515},"the-break-glass-admin","The break-glass admin",[12,518,519],{},"The accounts page asks two separate questions per account: give it a second factor, and close its non-interactive paths.",[12,521,522,523,525],{},"The stage 3 filter refuses to register while any enabled local account has no secret, so your break-glass admin has to be enrolled too. But ",[35,524,461],{}," says in its own header to keep a second admin account that still works. If enrolling an account also denied its network logons, you'd have no way left onto the machine the day the tile breaks. So enrolled means the tile accepts it, and denying SMB, WinRM and RDP is a separate checkbox. The page warns you when your selection leaves nothing that can reach the machine without the tile.",[59,527,529],{"id":528},"what-stays-manual","What stays manual",[12,531,532],{},"Some things Barista can't or shouldn't do for you:",[383,534,535,541,554,560],{},[386,536,537,540],{},[389,538,539],{},"The snapshot."," A VM can't snapshot itself. Barista stops at the points where it matters and asks you to confirm you took one.",[386,542,543,546,547,549,550,553],{},[389,544,545],{},"Your phone."," ",[35,548,511],{}," prints an ",[35,551,552],{},"otpauth:\u002F\u002F"," URI, you paste it into the wizard and it draws the QR code locally, without sending the secret anywhere. Scanning it and typing the code is up to you.",[386,555,556,559],{},[389,557,558],{},"Three risk checkboxes."," You're about to turn off lsass protection and load an unsigned DLL into the logon path.",[386,561,562,566],{},[389,563,564,362],{},[35,565,37],{}," It has its own button and its own dialog, and it's only offered when you picked a component that loads into lsass. Turning it off makes the machine a lot easier to loot, so no install step does it as a side effect.",[12,568,569,570,573],{},"The risk page also shows what to do if the machine doesn't boot after the network stage: load the offline SYSTEM hive from WinRE and delete the ",[35,571,572],{},"Auth0"," value. You see it before you need it.",[83,575,579],{"className":576,"code":577,"language":578,"meta":88,"style":88},"language-bat shiki shiki-themes gruvbox-dark-medium","reg load HKLM\\OFF C:\\Windows\\System32\\config\\SYSTEM\nreg delete HKLM\\OFF\\ControlSet001\\Control\\Lsa\\MSV1_0 \u002Fv Auth0 \u002Ff\nreg unload HKLM\\OFF\n","bat",[35,580,581,590,597],{"__ignoreMap":88},[48,582,583,587],{"class":93,"line":94},[48,584,586],{"class":585},"sBQf5","reg",[48,588,589],{"class":97}," load HKLM\\OFF C:\\Windows\\System32\\config\\SYSTEM\n",[48,591,592,594],{"class":93,"line":114},[48,593,586],{"class":585},[48,595,596],{"class":97}," delete HKLM\\OFF\\ControlSet001\\Control\\Lsa\\MSV1_0 \u002Fv Auth0 \u002Ff\n",[48,598,599,601],{"class":93,"line":204},[48,600,586],{"class":585},[48,602,603],{"class":97}," unload HKLM\\OFF\n",[59,605,607],{"id":606},"where-it-stands","Where it stands",[12,609,610,611,615,616,619,620,623,624,626,627,630,631,633],{},"The current version is ",[16,612,614],{"href":72,"rel":613},[74],"0.1.1",", built from Doppio ",[35,617,618],{},"d61192f"," and Ristretto ",[35,621,622],{},"069fb23",". Ristretto's Doppio submodule now points at ",[35,625,618],{}," too, so both halves use the same Doppio. 0.1.1 also fixes three things in the wizard: the Preflight page read a protected lsass as unprotected on a non-English Windows, because it matched the English text of WinInit event 12. An uninstall after Ristretto left Doppio's ",[35,628,629],{},"TacSubAuth"," in Auth0 when Ristretto had replaced it. And a PowerShell call could hang on output nobody read. CI runs the test suite on every push: the stage order, stopping at the first failed step, saving every finished stage, arming ",[35,632,507],{}," only when a reboot is pending, and the payload checks.",[12,635,636],{},"What it doesn't do yet:",[383,638,639,650,656,662],{},[386,640,641,644,645,647,648,362],{},[389,642,643],{},"No code signature."," SmartScreen will warn you, and the Integrity page says ",[78,646,361],{},". Check ",[35,649,357],{},[386,651,652,655],{},[389,653,654],{},"Not reproducible byte for byte."," If you build it yourself, you get different hashes for the exe and the DLLs, because MSVC and .NET write timestamps into them.",[386,657,658,661],{},[389,659,660],{},"No unattended mode"," and no config file. It's a wizard, you click through it.",[386,663,664,546,667,669],{},[389,665,666],{},"Enrollment opens a console window.",[35,668,511],{}," reads its prompts directly from the console, so it can't be driven from the wizard yet.",[12,671,672,673,675],{},"If you'd rather build everything yourself, the developer build is still there. ",[35,674,153],{}," fetches Doppio and Ristretto at the same pinned commits as the release, builds all three and opens the same wizard. A clone with local changes or a folder it doesn't recognise stops the run instead of being overwritten.",[12,677,678],{},"The README has everything else, including every flag of the bootstrap, what Barista writes to the machine itself and why, and how recovery works:",[12,680,681],{},[389,682,683],{},[16,684,687],{"href":685,"rel":686},"https:\u002F\u002Fgithub.com\u002FNobrac\u002FBarista",[74],"github.com\u002FNobrac\u002FBarista",[12,689,690],{},"MIT licensed, like Doppio and Ristretto. If a stage leaves your VM in a state Barista doesn't recognise, I'd like to hear which stage it was and what the machine did.",[692,693,694],"style",{},"html pre.shiki code .sM0OT, html code.shiki .sM0OT{--shiki-default:#EBDBB2}html pre.shiki code .sM2RB, html code.shiki .sM2RB{--shiki-default:#8EC07C}html pre.shiki code .s59W0, html code.shiki .s59W0{--shiki-default:#FABD2F}html pre.shiki code .s-UKz, html code.shiki .s-UKz{--shiki-default:#928374;--shiki-default-font-style:italic}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .svnLg, html code.shiki .svnLg{--shiki-default:#A89984}html pre.shiki code .sgVRN, html code.shiki .sgVRN{--shiki-default:#689D6A}html pre.shiki code .sMWUE, html code.shiki .sMWUE{--shiki-default:#83A598}html pre.shiki code .sBQf5, html code.shiki .sBQf5{--shiki-default:#FB4934}",{"title":88,"searchDepth":204,"depth":204,"links":696},[697,698,699,700,701,702,703],{"id":61,"depth":114,"text":62},{"id":146,"depth":114,"text":147},{"id":321,"depth":114,"text":322},{"id":365,"depth":114,"text":366},{"id":515,"depth":114,"text":516},{"id":528,"depth":114,"text":529},{"id":606,"depth":114,"text":607},"tools","2026-10-16","The 2FA series ends with two LSA components, an unsigned DLL in lsass and a dozen steps that have to happen in the right order. Barista is a wizard that does them one reboot at a time, from a single exe with every binary embedded and hash-checked.",false,"md","\u002Fimages\u002Fposts\u002Fbarista\u002Fcover.webp",[711,715],{"title":712,"description":713,"website":685,"image":714},"Barista on GitHub","The wizard, the release workflow and payload.lock.json. MIT licensed.","https:\u002F\u002Fgithub.githubassets.com\u002Fimages\u002Fmodules\u002Flogos_page\u002FGitHub-Mark.png",{"title":716,"description":717,"website":72,"image":714},"Barista v0.1.1","Barista.exe, SHA256SUMS and payload-manifest.json.",{},true,[366,322,516],"\u002Fposts\u002Fbarista",{"title":5,"description":706},null,"posts\u002Fbarista","2",[7,727,728,729,730],"lsa","2fa","credential-provider","security","9ROAbEaWsghNugnGjthc_P47V2LTp9IFWwSSQj8YBn8",[733,736,747,757,764,771,780,788,793,801,807,817,824,831,838,844,851,857,863,871,882,889,897,903,910,916,922,928,934,940,946,952,959,965,971,979,986,993],{"path":721,"title":5,"description":706,"date":705,"category":704,"alsoIn":734,"series":723,"tags":735,"readingTime":300},[7],[7,727,728,729,730],{"path":737,"title":738,"description":739,"date":740,"category":7,"alsoIn":741,"series":742,"tags":743,"readingTime":746},"\u002Fposts\u002Fwindows-2fa-gating-network-logons","Build Your Own 2FA for the Windows Logon, Part 3: Gating Network Logons","Part 2 refuses every network logon for an enrolled account, which makes the account safe and useless. Part 3 adds a gate you open once with a one-time code, so SMB, RPC and WinRM work again for a short window. In C++, with the full source.","2026-10-11",[704],"Doppio · 3-part series",[7,727,744,745,728,730],"ntlm","smb",35,{"path":748,"title":749,"description":750,"date":751,"category":704,"alsoIn":723,"series":723,"tags":752,"readingTime":233},"\u002Fposts\u002Fadhardenkit","ADHardenKit: Hardening AD Without Breaking It","LDAP signing, SMB signing, NTLM, Kerberos with AES only. Every hardening checklist has them. I wrote a tool that turns them on in an order that doesn't break the domain.","2026-10-07",[753,754,87,755,744,756],"active-directory","windows-server","hardening","kerberos",{"path":758,"title":759,"description":760,"date":761,"category":704,"alsoIn":723,"series":723,"tags":762,"readingTime":247},"\u002Fposts\u002Fntlm-analyzer","NTLM-Analyzer: Find Out Who Still Uses NTLM","Windows logs a lot of NTLM activity, but you have to piece it together yourself. I built a tool that shows which users and programs still use NTLMv1 or NTLMv2, and what already runs over Kerberos.","2026-10-03",[753,744,756,763,754],"auditing",{"path":765,"title":766,"description":767,"date":768,"category":7,"alsoIn":723,"series":742,"tags":769,"readingTime":770},"\u002Fposts\u002Fwindows-2fa-inside-lsa","Build Your Own 2FA for the Windows Logon, Part 2: Inside LSA","The credential provider from Part 1 only sees the logon screen. Part 2 goes into LSA to close the paths it can't reach, with an authentication package and an MSV1_0 sub-authentication filter in C++.","2026-10-01",[7,729,727,728,730],32,{"path":772,"title":773,"description":774,"date":775,"category":7,"alsoIn":776,"series":742,"tags":777,"readingTime":779},"\u002Fposts\u002Fwindows-2fa-credential-provider","Build Your Own 2FA for the Windows Logon","How a Credential Provider works and how to build a working TOTP 2FA for local Windows accounts in C++. With rate limiting, replay protection and logging.","2026-09-30",[704],[7,729,728,778,730],"totp",60,{"path":781,"title":782,"description":783,"date":784,"category":704,"alsoIn":723,"series":723,"tags":785,"readingTime":204},"\u002Fposts\u002Fadtierkit-active-directory-tiering","ADTierKit: Automatic AD-Tiering","I got tired of building tier models by hand, so I wrote a tool for it. One PowerShell script, one JSON file.","2026-08-06",[753,754,87,786,787],"tiering","laps",{"path":789,"title":790,"description":791,"date":784,"category":753,"alsoIn":723,"series":723,"tags":792,"readingTime":312},"\u002Fposts\u002Fldap-ldaps-and-active-directory","The thing with LDAP, LDAPS and Active Directory","Why LDAPS rarely fixes what security reports worry about, why you can't just block port 389, and what actually protects LDAP in Active Directory.",[],{"path":794,"title":795,"description":796,"date":797,"category":798,"alsoIn":723,"series":723,"tags":799,"readingTime":204},"\u002Fposts\u002Finstall-tor-exit-node","Install Tor Exit Node","How to run a Tor exit node on an anonymously rented VPS: paying with Monero, picking the provider and the country, and installing and configuring Tor.","2025-09-30","linux",[800],"tor",{"path":802,"title":803,"description":804,"date":805,"category":753,"alsoIn":723,"series":723,"tags":806,"readingTime":94},"\u002Fposts\u002Fconfigure-kerberos-armoring","Configure Kerberos Armoring","Kerberos Armoring (FAST) protects the Kerberos exchange against offline brute force, replay and tampering. How to enable it in your domain with a GPO.","2025-07-28",[756],{"path":808,"title":809,"description":810,"date":811,"category":812,"alsoIn":723,"series":723,"tags":813,"readingTime":816},"\u002Fposts\u002Fexchange-2019-install","Installation guide for Exchange SE and Exchange 2019","Install Exchange Server Subscription Edition (SE) or Exchange Server 2019 step by step and harden it, with WAF rules on the Sophos XG, SPF, DMARC, DKIM and more. The installation is the same for both versions.","2025-06-26","exchange",[812,814,815],"exchange-se","exchange-2019",47,{"path":818,"title":819,"description":820,"date":821,"category":753,"alsoIn":723,"series":723,"tags":822,"readingTime":300},"\u002Fposts\u002Fhow-ntlm-works-active-directory","How NTLM works in Active Directory","How NTLM proves that you know a password without sending it, what the domain controller does, the difference between NTLMv1 and NTLMv2, and why Microsoft is phasing it out.","2025-05-07",[744,753,823],"authentication",{"path":825,"title":826,"description":827,"date":828,"category":753,"alsoIn":723,"series":723,"tags":829,"readingTime":227},"\u002Fposts\u002Fadfs-installation","ADFS Installation","Basic installation guide for Active Directory Federation Services","2025-01-27",[830],"adfs",{"path":832,"title":833,"description":834,"date":835,"category":753,"alsoIn":723,"series":723,"tags":836,"readingTime":204},"\u002Fposts\u002Fexample-pass-the-hash-attack","Pass the Hash Attack Example","Example of a pass the hash attack","2025-01-22",[837],"pass-the-hash",{"path":839,"title":840,"description":841,"date":842,"category":753,"alsoIn":723,"series":723,"tags":843,"readingTime":247},"\u002Fposts\u002Fhow-kerberos-works-active-directory","How Kerberos works in Active Directory","How Kerberos works in Active Directory, step by step: the TGT, the service ticket and the request to the service, and why no password crosses the network.","2025-01-16",[756],{"path":845,"title":846,"description":847,"date":848,"category":7,"alsoIn":723,"series":723,"tags":849,"readingTime":204},"\u002Fposts\u002Fconfigure-credential-guard-computer-accounts","Configure Credential Guard for Computer Accounts","Windows Server 2025 can move computer account passwords into Credential Guard. How to enable it by GPO, and why turning it off means a new domain join.","2025-01-15",[850],"credential-guard",{"path":852,"title":853,"description":854,"date":855,"category":7,"alsoIn":723,"series":723,"tags":856,"readingTime":227},"\u002Fposts\u002Fconfigure-credential-guard-windows","Configure Credential Guard","How Credential Guard shields NTLM hashes and Kerberos tickets, how to enable it by GPO on older clients and servers, and how to check that it runs.","2025-01-13",[850],{"path":858,"title":859,"description":860,"date":855,"category":7,"alsoIn":723,"series":723,"tags":861,"readingTime":204},"\u002Fposts\u002Fosconfig-windows-server-2025-security","OSConfig - Security Settings for Windows Server 2025","OSConfig applies Microsoft's recommended security settings on Windows Server 2025 without GPOs. Install the module, list templates, enable a baseline.",[862],"osconfig",{"path":864,"title":865,"description":866,"date":867,"category":7,"alsoIn":723,"series":723,"tags":868,"readingTime":204},"\u002Fposts\u002Fsecure-iis-modsecurity","Secure IIS with Modsecurity","Installation guide to secure IIS with Modsecurity","2025-01-12",[869,870],"iis","modsecurity",{"path":872,"title":873,"description":874,"date":875,"category":753,"alsoIn":723,"series":723,"tags":876,"readingTime":306},"\u002Fposts\u002Fvcsa-certificate-windows-pki","Issue VCSA Certificate with Windows PKI","Replace the self-signed vCenter (VCSA) certificate with a SubCA certificate from your Windows PKI, using the VCSA Certificate Manager and WinSCP.","2025-01-09",[877,878,879,880,881],"ad-cs","pki","vmware","vcsa","vcenter",{"path":883,"title":884,"description":885,"date":886,"category":753,"alsoIn":723,"series":723,"tags":887,"readingTime":888},"\u002Fposts\u002Fwindows-pki-installation","Installation guide for a Windows PKI","Step-by-step guide for a two-tier Windows PKI with root CA, sub CA and a separate CRL server, plus certificate templates, OCSP and web enrollment.","2024-12-20",[877,878],36,{"path":890,"title":891,"description":892,"date":893,"category":894,"alsoIn":723,"series":723,"tags":895,"readingTime":306},"\u002Fposts\u002Fhack-the-box-administrator","Hack The Box: Administrator","Walkthrough for the \"Administrator\" Hack the Box Challenge","2024-11-19","hack-the-box",[896,7,753],"writeup",{"path":898,"title":899,"description":900,"date":901,"category":753,"alsoIn":723,"series":723,"tags":902,"readingTime":114},"\u002Fposts\u002Fsecure-active-directory-part-1","Secure Active Directory - Part 1","Part 1 of the guide to a secure Active Directory","2024-09-09",[],{"path":904,"title":905,"description":906,"date":907,"category":894,"alsoIn":723,"series":723,"tags":908,"readingTime":909},"\u002Fposts\u002Fhack-the-box-greenhorn","Hack The Box: Greenhorn","Walkthrough for the \"Greenhorn\" Hack the Box Challenge","2024-07-24",[896,798],12,{"path":911,"title":912,"description":913,"date":914,"category":894,"alsoIn":723,"series":723,"tags":915,"readingTime":300},"\u002Fposts\u002Fhack-the-box-runner","Hack The Box: Runner","Walkthrough for the \"Runner\" Hack the Box Challenge","2024-07-20",[896,798],{"path":917,"title":918,"description":919,"date":920,"category":894,"alsoIn":723,"series":723,"tags":921,"readingTime":94},"\u002Fposts\u002Fhack-the-box-ghost","Hack The Box: Ghost","Walkthrough for the \"Ghost\" Hack the Box Challenge","2024-07-18",[896,7,753],{"path":923,"title":924,"description":925,"date":926,"category":894,"alsoIn":723,"series":723,"tags":927,"readingTime":268},"\u002Fposts\u002Fhack-the-box-knife","Hack The Box: Knife","Walkthrough for the \"Knife\" Hack the Box Challenge","2024-07-15",[896,798],{"path":929,"title":930,"description":931,"date":932,"category":894,"alsoIn":723,"series":723,"tags":933,"readingTime":204},"\u002Fposts\u002Fhack-the-box-broker","Hack The Box: Broker","Walkthrough for the \"Broker\" Hack the Box Challenge","2024-07-10",[896,798],{"path":935,"title":936,"description":937,"date":938,"category":894,"alsoIn":723,"series":723,"tags":939,"readingTime":94},"\u002Fposts\u002Fhack-the-box-permx","Hack The Box: PermX","Walkthrough zur \"PermX\" Hack the Box Challenge","2024-07-08",[896,798],{"path":941,"title":942,"description":943,"date":944,"category":894,"alsoIn":723,"series":723,"tags":945,"readingTime":204},"\u002Fposts\u002Fhack-the-box-lame","Hack The Box: Lame","Walkthrough zur \"Lame\" Hack the Box Challenge","2024-07-06",[896,798],{"path":947,"title":948,"description":949,"date":950,"category":894,"alsoIn":723,"series":723,"tags":951,"readingTime":227},"\u002Fposts\u002Fhack-the-box-analytics","Hack The Box: Analytics","Walkthrough zur \"Analytics\" Hack the Box Challenge","2024-06-30",[896,798],{"path":953,"title":954,"description":955,"date":956,"category":894,"alsoIn":723,"series":723,"tags":957,"readingTime":233},"\u002Fposts\u002Fhack-the-box-sense","Hack The Box: Sense","Walkthrough zur \"Sense\" Hack the Box Challenge","2024-06-28",[896,958],"freebsd",{"path":960,"title":961,"description":962,"date":963,"category":894,"alsoIn":723,"series":723,"tags":964,"readingTime":312},"\u002Fposts\u002Fhack-the-box-mailing","Hack The Box: Mailing","Walkthrough zur \"Mailing\" Hack the Box Challenge","2024-06-26",[896,7],{"path":966,"title":967,"description":968,"date":969,"category":894,"alsoIn":723,"series":723,"tags":970,"readingTime":204},"\u002Fposts\u002Fhack-the-box-jerry","Hack The Box: Jerry","Walkthrough zur \"Jerry\" Hack the Box Challenge","2024-06-20",[896,7],{"path":972,"title":973,"description":974,"date":975,"category":798,"alsoIn":723,"series":723,"tags":976,"readingTime":94},"\u002Fposts\u002Flinux-ssh-telegram-notifications","Setting up notifications via Telegram for SSH login\u002Flogoff","Get a Telegram message every time someone logs in to or out of your Linux server over SSH, with a Telegram bot, a small script and PAM.","2024-06-01",[977,978],"ssh","monitoring",{"path":980,"title":981,"description":982,"date":983,"category":894,"alsoIn":723,"series":723,"tags":984,"readingTime":985},"\u002Fposts\u002Fhack-the-box-forest","Hack The Box: Forest","Walkthrough zur \"Forest\" Hack the Box Challenge","2024-05-20",[896,7,753],16,{"path":987,"title":988,"description":989,"date":990,"category":812,"alsoIn":723,"series":723,"tags":991,"readingTime":94},"\u002Fposts\u002Fpowershell-connect-to-exchange-online","Verbindung zu Exchange Online mit Powershell","Wie man sich mit PowerShell mit Exchange Online verbindet: das Modul ExchangeOnlineManagement installieren, aktuell halten und die Verbindung herstellen.","2023-10-23",[992,87],"m365",{"path":994,"title":995,"description":996,"date":997,"category":812,"alsoIn":723,"series":723,"tags":998,"readingTime":94},"\u002Fposts\u002Fexchange-october-2023-updates","Exchange Server","Neue Sicherheitsupdates (Oktober 2023)","2023-10-18",[],1792192463027]