WhyNot.Failhttps://whynot.fail/Recent content on WhyNot.FailHugo -- gohugo.ioen-usThu, 24 Oct 2024 00:00:00 +0000Nix/NixOS is the new “dotfiles golf” - and that’s awesomehttps://whynot.fail/nixos/the-new-dotfile-golf/Sat, 10 Aug 2024 00:00:00 +0000https://whynot.fail/nixos/the-new-dotfile-golf/<p>For the past month I’ve been transitioning to NixOS, both my work laptop and my personal desktop.</p> <p>It’s been an amazing voyage. The learning curve is steep for the first 1-2 days, till you grasp the whole idea but then that’s mostly it.</p> <p>The language syntax is a bit weird and ugly but it really is quite simple - and I say that with 0 background in math or functional languages.</p>

For the past month I’ve been transitioning to NixOS, both my work laptop and my personal desktop.

It’s been an amazing voyage. The learning curve is steep for the first 1-2 days, till you grasp the whole idea but then that’s mostly it.

The language syntax is a bit weird and ugly but it really is quite simple - and I say that with 0 background in math or functional languages.

You quickly learn that “RTFM” is not a thing in Nix since there’s no manual and the tools at your disposal aregrep.app to see what others did (though due to the frequent changes in how stuff work could mislead you) and theNixOS forums which is amazing.

The question that arises before you even consider scrapping what you’ve been building for the past N years is “why? yea all the hipsters use it but WHY?”

I was very resilient too since every month or so something new and shiny comes up that nobody asked for, everyone around you loses their mind about it and 2 weeks later it’s abandoned.

welp, I have 2 extremely solid reasons: reproducibility and stability

Stability

The idea in NixOS is that your whole OS is split in configurable and non-configurable parts. The configurable is managed by theconfiguration.nix file. The non-configurable is most probably files under your home directory, like browser files regarding your sessions n stuff that doesn’t make sense to configure statically.

Stability comes from the fact that after you change yourconfiguration.nix you have torebuild and thenswitch to the new generation for it to take effect. Every time yourebuild, a new “version” of your whole OS (only the managed part, the rest remain intact) gets created andswitching to it activates it.

That means that you’re able to do something magic:rollbacks. Did you break your fstab? Boot to the previous working generation and you’re good to go! Did the latest update break your browser? rollback! The boot manager is configured to give you a choice of the last N generations so you just pick what you want - THAT easy, no weird arcane magic.

Reproducibility

That leads us to the second amazing feature: reproducibility.

I know that everyone talks about it when nix comes in the discussion but it does actually affect you, it’s not just a “good principal”.

Imagine being sure that your hacky script that logs you into your machine with port knocking works EVERY time - and when I say every time, I mean it. If the module (aka piece of nix code) that configures it compiles, it WILL work. Just formatted? it works. Moved from i3 to Plasma 6 and btrfs? it works.

It really empowers you and gives a much greater pleasure into optimizing small aspects of your desktop since you know that they’ll be there for quite a long time and are much harder to randomly break.

Golfing

So that brings us to this post’s title: dotfile golfing.

The dotfiles now hold a much greater power. It’s super easy to set up and keep 2 machines in sync. Just define some host-specific quirks for each machine (e.g. a desktop doesn’t needlaptop-tools ) and you’re good to go.

That has led all the people with weird setups (⇒ people that have adotfiles repo) to have a much, MUCH better experience. They don’t have to keep track of what they install and how so that they can set up the whole thing again.

Sets of dotifile hacks are now their own “packages” (flakes in nix world) that anyone can use -stylix for example, which tries to do the impossible: make the theming/styling consistent across the whole OS, from NeoVim to GTK to Plymouth, all with the same colors and wallpapers.

Bonus

You also get the following amazing features as a bonus:

Formatting has become way, WAY easier. After setting up the partitions in a new machine,nixos-install --flake github.com:dzervas/dotfiles will set up the new machine. The next reboot will have everything ready for me - yes even that port knocking script - honestly the biggest hurdle when setting up a new machine after your nix config has stabilized is logging in to every service & website you use

You can even create an ISO with your whole config ready to go with GitHub actions (as I didhere) so you can work on a new machine without even formatting. Boot the ISO and do whatever needs doing. My work laptop is now officially disposable!


My nix config:dotfiles

Fusion 360 Internals: Trying to re-invent Fusion’s GUI (and failing)https://whynot.fail/reversing/fusion-360-internals/Sat, 25 Mar 2023 00:00:00 +0000https://whynot.fail/reversing/fusion-360-internals/<p>This is one of those weird ones where I try to do something batshit crazy and I end up inevitably failing. It was almost too clear that this is gonna be the path but I needed something to hyperfocus on to have some stress-free moments.</p> <p>This is how I tried to use only the engine/rendering canvas of Fusion and re-implement the whole GUI around it from scratch (toolbars, browser, history bar, etc.).</p>

This is one of those weird ones where I try to do something batshit crazy and I end up inevitably failing. It was almost too clear that this is gonna be the path but I needed something to hyperfocus on to have some stress-free moments.

This is how I tried to use only the engine/rendering canvas of Fusion and re-implement the whole GUI around it from scratch (toolbars, browser, history bar, etc.).

Wait what? What do you mean? Why? What?

Ok so let’s take it from the top. I love Fusion’s UX. It’s amazing. Everything is where it should be and stuff just work as you expect them. It does some weird fuckery when you try to direct model (organic handles, mouse shells, etc.) but it’s not the point of the software anyway. And almost nobody can rival it in my eyes. I’ve tried Solidworks, OnShape, BricsCAD, FreeCAD, Solid Edge, SolveSpace, Rhino 3D with Grasshoper. I’ve tried it all. I’ve seen it all. I’m dissapointed.

“Awesome, where’s the problem”, I can hear you say.

Linux. The problem is Linux. Running Fusion on Linux is… shitty. Whilecryinkfly has done an amazing work on the matter, it’s not good enough for me. Crashes, glitches, overlayed artifacts across all workspaces and in general it makes the app quite cumbersome. It kills the UX.

So there were 3 solutions to that problem:

  • Pivot to Windows - nope, I prefer to leave computers behind
  • Windows VM - It sucks, it’s slow and it also sucks
  • Hook Fusion using frida to fix the artifacts/problems (and maybe give the solutions to Autodesk almost ready to implement) - too hard, too specific and too fragile. An update could render my whole work useless
  • Fix wine - it’s actually the best solution as it will benefit more apps. But I thought it would be harder (little did I know…) Instead, I chose the 4th (5th?) option: Use the “hard parts” of Fusion by re-write the GUI as an open-source shell. Sure it would require “some” reversing but at some point I could have a Window with JUST the Canvas in it (where the 3D objects are drawn).

Before I let you know my evil plan (according to Autodesk I imagine), let’s talk a bit about the guts of Fusion

Fusion 360’s GUI internals

Fusion is written completely in Qt 5, start to finish. At the time of writing (25 March 2023) it uses Qt 5.15.2, the upstream LTS version.

They use MANY of Qt’s features and every component is written in a different “Qt manner”. Is the whole app a Qt demonstration? I guess we’ll never know…

  • The whole window is aQGuiApplication window
  • The top toolbar and the botton design history bar are regularQWidgets, buttons, labels, icons, tooltips and the rest
  • All the sidepanels and overlays (Learning Center, Data Panel, Browser, Comments and Notification Center) are all HTML/CSS/JS that run inside differentQtWebEngines with a customCEF that gives access to the JS→C++ bridge. That bridge is calledFermontJS and talks with theNeuron engine BTW
  • I have no idea where, but QtQuick is involved somwhere
  • The main “viewport” orShell as Autodesk calls it (the main gray window that 3D stuff appear) is something… weird. Something very weird. It’s a class inside theNuBase10.dll that is calledNu::GraphicsCanvas The last bit is what we’re looking for. TheQtWidgets parts can be re-written. The toolbar is dynamically generated based on some XMLs, the design history is by definition programmatically populated, HTML/CSS/JS components are just in the installation folder for anyone to grab,FermontJS is just a node script andNeuron can be run in its own process (I think???).

Not easy to do all that but certaintly doable.The hard part would be that damnedGraphicsCanvas. It has many other names,Canvas,QtCanvas (sub/super classes) but its the same damned thing. If I could make an instance of it on its own window it would prove that I can actually run the part of Fusion that handles the CAD engine and renders what the user sees.

How would that help you with wine?

The plan for the “final form” of the project was:

  1. Wrap the required DLLs using winelib
  2. Dynamically link against them a Rust binary that:
  3. Cross-compile that binary for every platform
  4. Create an installer that pulls the required DLLs so that Autodesk won’t cry us a river for “redistribution” Not an easy project but kiiiiiinda, maaaaaybe doable.

So what’s the problem(s)?

First of all, theGraphicsCanvas ain’t “just aQtObject”. At all. It’s too intertwined with commands, threads, events,Shells,Workspaces, etc. for me to figure out. I just don’t get it. Couldn’t they just wrap aQOpenGLWidget or aQSurface and be done with it? Apparently not…

While they DID do both of the above, they also did sooooooo much more beyond that that my reversing skills started laughing hysterically - and not the good kind of laugh, the “oh boy what the actual fuck is this” kind of laugh.

Even so, I thought to start throwing shit to the wall till something sticks. I see the canvas gone, or glitched, or (praying) in a separate window and I whipped out frida.

But frida seems to be as confused as me when dealing with C++ MSVC ABI when dealing with object instances on Windows. I just tried callingQWindow(nullptr)::QWindow from theQt5Gui.dll and after that callshow()::QWindow. Frida wouldn’t have me do my shit. Frida was done with me.

And now?

This is the point where I give up. This might seem a small post but it took me a great 6 months to learn what I did. Did you know there’s a “Command Panel” in Fusion? Did you know that there’s agithub repo just describing the commands in it? Did you know that you can dump the Qt tree of Fusion while its running?

Useful Fusion commands (Opened by File > View > Show Text Commands (Ctrl-Alt-C), all commands are Txt):

TextCommands.List/hidden- Show all text commandsOptions.DebugEnvironment/show- Show a debug environment, didn't see something interestingOptions.showAllCommands/on-???Options.showAllOptions- Make MANY preferences visibleToolkit.DumpQt- Dump QT object info. [/styles] [/class] [/rect]

Also got to learn about C++ RTTI and vftables and that nothing can be compared to the hatred that I have for that FUCKING LANGUAGE THAT HELL GIFTED TO US.

REALLY. WHAT THE FUCK IS WRONG WITH YOU PEOPLE.

If someone is able to make a PoC that shows that indeed a Canvas can be drawn on its own (with some boilerplate), I’ll be more than happy to open this can of worms.

Also I re-implemented Fusion’s installer in python that also knows about Fusion’s build versions,check it out.

C ya

The art of cracking softwarehttps://whynot.fail/reversing/the-art-of-cracking-software/Wed, 02 Nov 2022 00:00:00 +0000https://whynot.fail/reversing/the-art-of-cracking-software/<p>As the years have gone by, it seems that cracking software is more and more synonymous to “malware”. As this world no longer knows how to operate in a manner of doing something for the common good, selfless moves that would give access to people that can’t bear the stupid “entry price” have been shadowed by moves that replace that “entry price” with remote access instead of money. It pains me and makes me sad, but at least I can share some aspect of it, as I’d rather not go to jail.</p>

As the years have gone by, it seems that cracking software is more and more synonymous to “malware”. As this world no longer knows how to operate in a manner of doing something for the common good, selfless moves that would give access to people that can’t bear the stupid “entry price” have been shadowed by moves that replace that “entry price” with remote access instead of money. It pains me and makes me sad, but at least I can share some aspect of it, as I’d rather not go to jail.

For some reason I’m not completely sure, I’ve picked up the hobby of cracking niche softwares’ licensing mechanisms. Maybe it’s because that I know for a fact that they can be cracked - something that isn’t given for hacking cloud-based software.

This is a research post. I don’t use or share my cracks. I do it for fun. Please don’t hurt me.

Defining the target

My targets are exclusively Windows programs, but I’m sure a lot of the described techniques apply to any OS.

Each time I start cracking a program, I’ve got to set a clear target. Most times is “permanent license that gives me access to everything” but that requires to know the following:

  • Is there a trial version? If yes:
  • Forget about any kind of cloud-based features (cloud save, cloud-based computing, etc.)
  • Is the license “just a serial number” or a whole file (binary or not)?
  • Does the software provide means of offline license activation?
  • What language is the app written in?
  • Do we have any kind of debug symbols?
  • Any kind of obfuscation or anti-reversing? The only blocker in the above questions is if we have no access to the premium binary. Maybe the URL to download it is tucked somewhere inside the trial binary. If not, too bad, find something else.

I’d also stop as soon as I found that the app has anti-reversing or serious obfuscation. I’d really like to have fun and not spend the good part of a year for a single app. I’m not a good reverser anyway and I don’t want to be - these people are scary.

Another part of my cracking adventure is developing the “perfect crack”. The one that tinkers the app the least and allows me to maintain it across versions. I don’t want just to patch a DLL. It’s dirty. We’ll see better techniques further down.

First impressions

Play a bit around with the software see what it does. Identify useful strings (likeTrial orExpires) inside the app so you’ve got stuff to search.

How does it behave if you give it a wrong serial number? If you disable the internet? Where does it store license stuff? Maybe in the registry? Are there any interesting keys in there? If the license is stored in a file, poke it. Is it encrypted? Signed? Has a checksum?

At this point there are no wrong directions. Poke the program and start building confidence in the app. What it means to run correctly. You should crash the app at least once. Don’t be afraid, you can just re-install it.

Network inspection

Fire up Burp and pass the whole VM traffic through it (you’re using a VM right? RIIIIGHT???)

Identify the URLs and check for SSL pinning. Then install Burp’s root cert in the VM and check again.

If it’s SSL pinned bypassing it shouldn’t be that hard (we’ll see some examples later)

Right now you’re looking for the following:

  • Does the serial number get sent to the backend?
  • If yes, check the responses of correct and incorrect license numbers
  • If not, check for kinda weird-looking strings, encrypted strings and signatures. Maybe the license is used to generate another string to obfuscate it over the wire There’s a pretty good chance that right now you’ve found already a solid entrypoint. The app sends some computer based fingerprint with the license key to the licensing server and expects a structured response that describes the kind of license that we have.

In my experience following this route has not been fruitful. In all of such encounters the request and response are signed and sometimes even encrypted. But the most problematic aspect is identifying the required structure that the app expects. Instead of22-dec-2022 that the expiration date is set you try22-dec-2032 - after bypassing the signature check of course. But for some reason it doesn’t work - data are encoded elsewhere as well? Maybe if you changetrial topremium? Or toultimate? Why are there both strings inside the app? Is that case sensitive?

These might seem like easy problems but, let me tell you, they’re definitely not. Compilers have gone mental with optimization and understanding a C++ object through reversing is it’s own mountain. How would you know thatultimate needs ais_network_license to false - whiletrial does not?

From all the programs that I’ve cracked, I’ve never found one that does a “simple enough” network call to check the license. They all use some kind of licensing solution that has signatures and encryptions n stuff that make network-based cracking as hard as “regular” cracking (hooking/patching n stuff).

So now what?

Dynamic Instrumentation - Native apps

Let me introduce you to the amazing world of: 🌈frida🌈

It’s a stupidly powerful dynamic instrumentation framework, mainly targeting mobile apps but it works great on all Desktop OSes as well. Think of it like Inspect Element for native apps.

It works by injecting a JavaScript Engine inside the target process. That essentially allows you to inject or even replace native function with JavaScript code. Here for example we hook the debugging output the target app runs:

letOutputDebugStringW_export=Module.getExportByName("kernel32.dll","OutputDebugStringW");letOutputDebugStringW_new=newNativeCallback((str) => {// Redefine the code executed - yeap, plain javascript.// `str` is gonna be a pointer as we tell further down.// As the return type is void, we don't have to return anything// Since this is a pointer, we can treat it in any way we like. Here we read it as Utf16 - part of the frida APIconsole.log(str.readUtf16String()); },"void",// Return type ["pointer" ]// Argument list. They will be passed to the above function as regular arguments);

The above can then be run as follows:

frida.exe-fMyAwesomeApp.exe-lHookDebugStringW.js

This will spawn the app but you can also hook onto an already running process with-n flag instead of-f. After that you’re thrown into an interactive JS shell that you can enter commands or change the script that is automatically re-applied once it changes on disk. I can’t possibly overstate how powerful this tool is. And it doesn’t stop there!

The exact reason of why would you hook a debug output is not the point. That could be an exported symbol of the program or even one of its DLLs. But what if you just wanna search for a bunch of function names and wanna see if they get called in the specific flow that you’re researching? Enterfrida-trace.

Instead of writing hooks like the above over and over, that tool does most of the job for you and can also pattern match function names. Almost my first command when I start the reversing phase is the following:

frida-trace.exe-nMyAwesomeApp.exe-i'MyAwesomeApp.exe!*License*'

I run that right before I click some kind of license checking button after I’ve entered the license string and I check to see if any function with a name that matches the pattern*License* (note: case sensitive) inside the moduleMyAwesomeApp.exe (note: case sensitive as well - many times the module name is in a different case than the file. UseProcess.enumerateModulesSync() inside the frida shell) fires up. I’m limiting the search in that module to avoid hooking thousands of functions - which is a very good recipe for an instant crash. You can either make the pattern a bit more targeted and remove the module part or change the module to a spicy named DLL. You can also hook all the functions of a module with-I liblicense_of_MyAwesomeApp.dll but again, if the exports are too many it’ll crash.

At this point, for the not-so-experienced crackers, I should note that the whole time I’m talking about functions that have exported symbols. If the app has stripped the names of the functions and the function that you’re aiming for is called from inside the module, the aforementioned technique will bear no fruits as there won’t be any functions found to hook. The windows-native functions though (user32.dll orkernel32.dll for example) will always work as those DLLs have well known exports. It’s a very accurate way of finding out the environment variables that the app accepts, WMI queries that it does, registry keys that it uses and maybe even some crypto stuff that it uses to check the license.

Reversing - Native apps

I don’t know what you’re expecting here but I’m not a good reverser. At all. Fire up ghidra and start looking for strings and go back from there. I’ve got one piece of a one-liner though to find spicy DLLs fast:

fd . ~/.wine/drive_c/Program\Files/MyAwesomeApp -H -t f -x sh -c'strings -a -e l "{}" | rg -i "license" && echo -e "\t>{}"'

What this does is runstringsto all the files recursively under~/.wine/... but with a twist: the-e l flag. This makes all the difference. You see Windows like 16 bit little endian characters. But not always. Maybe big endian (-e b) or maybe regular ASCII (no-e flag at all). This note took me a week to find out. Cheers.

While it’s very tempting, don’t invest much time finding “a single function that if returns true everything is super-premium-ultimate-version”. Nowadays everyone loves object orientation and most often than not a “subtle” change could require huge changes in the object that represents the license. I have however stumbled upon such a marvelously written software!

It’s one of the most widely used software in its market and: IT’S CLOUD BASED. Yeap. It’s mostly an electron app that loads remote content and I just didn’t even try to crack it for months. “It should load the code that is required for my specific license” I thought. NOP! It had anisUltimate function that when hooked to returntrue, I was magically Ultimate.

Most of the other software though weren’t that nice. Even apps that share just a tiny fraction of the market used some kind of licensing solution that as said before has some difficulty - Stripped symbols, encryption, signing, public/private keys and even sometimes statically compiled crypto functions.

A word on keygens

I think that key generators are the epitome of art in terms of cracking. It’s so slick and not intruding and sometimes quite hard to counter-measure from the perspective of the developer so many times it’s resilient to updates. But it’s hard. Very hard.

I’ve stumbled upon a C# app that I cracked using a keygen. I found a “magic license key” to put it in offline mode so that it accepts license keys that are checked using some math. But it used some archaic Windows hashing function that was a pain to re-implement and required some very weird math. It was also hidden in plain site - The functionCheckLicense was never called (and it also had some even more weird math that took me 3 days to understand that make no actual sense) and the actual function was named something likeCalculateOrbitalTrajectory. The only way that I could find that was through dynamic instrumentation.

On another app I cracked the public DSA-512 public key that it used to verify the license signature. I had already cracked it through hooking but I wanted to completely own it so I cracked the key - I never got to use it tho as it needed some weird transformations and I got bored. Again, the structuring of data is a huge roadblock. Here’s though how I cracked a DSA-512 public key in 2 days (there are MUCH better and faster ways to do it but that’s the only way it worked for me - also I’m bad at cryptanalysis):

# All the key data have been changed# Extract the PEM public key from inside the binaryopenssl dsa -pubin -in anotherAwesomeApp_public_key.pem -noout -modulusread DSA keyPublic Key=2A0ABA86F22281B123F33D9E073AC921C0F2BCB0114C07F632129B64C3CA4181D84C998C2556DC69CB30E0D6B7CB761274AAFC6834FE74D6721E6EA6BCD68DEA# Hex to decimal$ echo"ibase=16;2A0ABA86F22281B123F33D9E073AC921C0F2BCB0114C07F632129B64C3CA4181D84C998C2556DC69CB30E0D6B7CB761274AAFC6834FE74D6721E6EA6BCD68DEA" | bc22019134240820916317814169763607118015464182266127018258054642617293\88614872096293260765941335270405591230469600688971077042627869124706\949973008545385962# And then run [cado-nfs](http://cado-nfs.gforge.inria.fr/) through docker to# factor the number (steps from [here](https://www.doyler.net/security-not-included/cracking-256-bit-rsa-keys)):$ docker run -d --name anotherAwesomeApp_public cyrilbouvier/cado-nfs.py2201913424082091631781416976360711801546418226612701825805464261729388614872096293260765941335270405591230469600688971077042627869124706949973008545385962$ docker logs -f anotherAwesomeApp_publicUnable to find image'cyrilbouvier/cado-nfs.py:latest' locallylatest: Pulling from cyrilbouvier/cado-nfs.py43c265008fae: Pull complete50baea060b67: Pull complete5f3e0aed5ee6: Pull complete80c73fc9483b: Pull completeDigest: sha256:83513a532bc3cfc09ddc44e9c12b9283ace37736fed29f6259cb2b98a1342ab3Status: Downloaded newer imagefor cyrilbouvier/cado-nfs.py:latestInfo:root: Using default parameter file /cado-nfs/share/cado-nfs-2.2.1/factor/params.c155Info:root: No database exists yetInfo:root: Created temporary directory /tmp/cado.gcsugjj0Info:Database: Opened connection to database /tmp/cado.gcsugjj0/c155.dbInfo:root: Set tasks.threads=6 based on detected physical cpusInfo:root: tasks.polyselect.threads=2Info:root: tasks.sieve.las.threads=2Info:root: slaves.scriptpath is /cado-nfs/binInfo:root: Command line parameters: /cado-nfs/bin/cado-nfs.py2201913424082091631781416976360711801546418226612701825805464261729388614872096293260765941335270405591230469600688971077042627869124706949973008545385962Info:root: If this computation gets interrupted, it can be resumed with /cado-nfs/bin/cado-nfs.py /tmp/cado.gcsugjj0/c155.parameters_snapshot.0Info:Server Launcher: Adding e13824a36734 to whitelist to allow clients on localhost to connectInfo:HTTP server: Using non-threaded HTTPS serverInfo:HTTP server: Using whitelist: localhost,e13824a36734Info:Complete Factorization: Factoring2201913424082091631781416976360711801546418226612701825805464261729388614872096293260765941335270405591230469600688971077042627869124706949973008545385962Info:HTTP server: serving at https://e13824a36734:41869(0.0.0.0)Info:HTTP server: For debugging purposes, the URL above can be accessedif the server.only_registered=False parameter is addedInfo:HTTP server: You can start additional cado-nfs-client.py scripts with parameters: --server=https://e13824a36734:41869 --certsha1=313aa0820967f6db061e8fc9cbf2bde7ecdacab5Info:HTTP server: If you want to start additional clients, remember to add their hosts to server.whitelistInfo:Client Launcher: Starting client id localhost on host localhostInfo:Client Launcher: Starting client id localhost+2 on host localhostInfo:Client Launcher: Starting client id localhost+3 on host localhostInfo:Client Launcher: Running clients: localhost+3(Host localhost, PID 16), localhost+2(Host localhost, PID 14), localhost(Host localhost, PID 12)Info:Polynomial Selection(size optimized): StartingInfo:Polynomial Selection(size optimized):0 polynomials in queue from previous runInfo:Polynomial Selection(size optimized): Adding workunit c155_polyselect1_0-1000 to databaseInfo:Polynomial Selection(size optimized): Adding workunit c155_polyselect1_1000-2000 to databaseInfo:Polynomial Selection(size optimized): Adding workunit c155_polyselect1_2000-3000 to database...Info:Square Root: StartingInfo:Square Root: Creating file of(a,b) valuesInfo:Square Root: finishedInfo:Square Root: Factors:279 104569920747<hidden>81898074331Info:Square Root: Total cpu/real timefor sqrt: 0.02/0.0144372Info:Polynomial Selection(size optimized): Aggregate statistics:Info:Polynomial Selection(size optimized): potential collisions: 71168.8Info:Polynomial Selection(size optimized): raw lognorm(nr/min/av/max/std): 72294/45.370/55.413/60.780/0.874Info:Polynomial Selection(size optimized): optimized lognorm(nr/min/av/max/std): 67782/45.250/50.101/56.280/1.689Info:Polynomial Selection(size optimized):10 best raw logmu:Info:Polynomial Selection(size optimized):10 best opt logmu:Info:Polynomial Selection(size optimized): Total time: 49493.9Info:Polynomial Selection(root optimized): Aggregate statistics:Info:Polynomial Selection(root optimized): Total time: 4050.98Info:Polynomial Selection(root optimized): Rootsieve time: 4050.39Info:Generate Factor Base: Total cpu/real timefor makefb: 21.54/5.23901Info:Generate Free Relations: Total cpu/real timefor freerel: 271.45/44.1077Info:Lattice Sieving: Aggregate statistics:Info:Lattice Sieving: Total number of relations:48074999Info:Lattice Sieving: Average J: 7752.25for1680511 special-q, max bucket fill: 0.732933Info:Lattice Sieving: Total CPU time: 2.90978e+06sInfo:Filtering - Duplicate Removal, splitting pass: Total cpu/real timefor dup1: 104.66/78.7711Info:Filtering - Duplicate Removal, splitting pass: Aggregate statistics:Info:Filtering - Duplicate Removal, splitting pass: CPU timefor dup1: 78.7sInfo:Filtering - Duplicate Removal, removal pass: Total cpu/real timefor dup2: 641.15/153.957Info:Filtering - Singleton removal: Total cpu/real timefor purge: 427.7/143.297Info:Filtering - Merging: Total cpu/real timefor merge: 631.74/620.553Info:Filtering - Merging: Total cpu/real timefor replay: 103.78/94.0045Info:Linear Algebra: Total cpu/real timefor bwc: 160799/0.000371933Info:Linear Algebra: Aggregate statistics:Info:Linear Algebra: Krylov: WCT time 18123.13Info:Linear Algebra: Lingen CPU time 379.27, WCT time 81.51Info:Linear Algebra: Mksol: WCT time 9798.28Info:Quadratic Characters: Total cpu/real timefor characters: 78.49/28.6099Info:Square Root: Total cpu/real timefor sqrt: 0.02/0.0144372Info:HTTP server: Shutting down HTTP serverInfo:Complete Factorization: Total cpu/elapsed timefor entire factorization: 3.12641e+06/720361Info:root: Cleaning up computation data in /tmp/cado.06lc2ugg279 104569920747<hidden>81898074331# Unfortunately that's as far as I got :)

Dynamic Instrumentation & Reversing - C# apps

One word:dnSpy. Again, a gift given by gods. Unfortunately frida won’t work with the C# runtime but dnSpy has your back. It fully decompiles the app and is an amazing debugger.

The exact same principals as above apply but the problem is that the resulting crack can’t be a javascript file and this raises a problem that I’ve been obsessing about for the past two weeks: Crack deployment.

As I said in the prologue, I like clean cracks that are transparent to the user (can inspect them easily) and are able to be maintained for future proofing. JavaScript is an amazing solution to the above problems (although it has some others of its own) but as frida isn’t available for C#, we can’t use it. Of course we could patch the binary with dnSpy but patched binaries just don’t cut it for me. They’re dirty. We’ll talk about this problem later.

Dynamic Instrumentation & Reversing - Java apps

Well here, we’ve got a problem. I was stunned to find out that the main target of frida, the Java VM is actually the mobile Java VM. Frida-ing “Regular” Java, running on Windows and Linux won’t do it. It spits out some errors about some not found classes (that contain the nameZygote which is an Android-y name) and doesn’t work. I was heart broken and at that point I didn’t go any further.

Of course there’s JadX for reversing, but it doesn’t offer a debugger for desktop apps either. Why does everyone forget that Java runs on desktops, is above me.

Maybe I’ll come around it and find good tooling around Java, who knows. If you happen to know good tools, leave a comment below

Crack deployment

As we’re reaching the end of this post (yes, it has one, even if it doesn’t seem like it) I’d like to close with the problem I’ve been burdened for the last two weeks. Let’s say I’ve written some good frida scripts that do their job and I’ve patched a C# DLL as a PoC. Now what? I don’t want to have to run the app through frida and have a statically patched binary! That’s dirty! When the app updates, I’ll have problems. I break the PE’s signature, it’s hard to replicate, it’s hard to explain and it’s not transparent. I’ve found the following solutions till now - unfortunately without a good implementation (yet?):

  • Create an AppInit_DLL (for what that is clickhere) that is app-aware so that whenMyApp.exe loadsuser32.dllfrida-gadget can be injected or a nicely written Rust dll can be injected. I’ve not seen a tool like this but I’d like to develop one.
  • Patch the target exe to include our custom frida-gadget/DLL as a DLL import and load it. This differs than static patching as there’s a single global script to patch all of our cracked exes and the change is almost self-explanatory. When the exe is cracked, it’ll have alibcrack.dll import that does all the hooking job. Simple and clean - with an asterisk though as that change breaks the PE’s signature, something that I’ve got no idea how big of a problem is. I’ve tried using theLIEF python library but I wasn’t able to run the exe after patching successfully afterinjecting the frida-gadget library - I’ve even opened anissue about it
  • Maybe find DLLs that the app optionally searches for and if found load them? That’s too app-specific though and prone to break across updates (maybe it requires different exports or it changes the program behavior in a way that we don’t like).
  • ??? - please comment if you have a good idea

Closing

I still don’t get why companies charge such a stupid amount of money for their software when we’re talking about hobbyist clients. It’s a win-win. You’ll never make a 50k$/year sale to that person but if you give it to them for free, it’s almost sure that they’re gonna root for you and advertise you. For free. Also if they land a job around the market you’re in, there’s a pretty good chance that they’ll push the company to buy your software - even for 50k/year.

Maybe I’m too naive. Maybe I “don’t get business”. Truth is, I’m not good at that “capitalism” game.

On the other hand, I tend to draw a line on apps that I crack. There are some amazing software that cost something very reasonable and they get regular updates, good communities n stuff. I like to support them if I can.

In any case, cracking is not that hard, it just requires time. You get to dead ends quite often but it’s not hard to understand what you see. Most times, when I’m stuck I start from a new lead. Eventually everything falls together. Give or take, a month is enough to crack “most” programs (I’m not talking about apps around computer security, such as IDA Pro. I’ve heard it’s a HUGE undertaking).

This post is written in Notionhttps://whynot.fail/coding/notion-blog/Sun, 26 Jun 2022 00:00:00 +0000https://whynot.fail/coding/notion-blog/<p>I’ve been searching for a way to write blog posts through a beautiful, mobile-friendly interface for almost two years.</p> <p>Notion was always a very good answer but the code required to make it work was always keeping me back. But I finally did it, this blog’s content is now fully hosted in Notion</p> <p><img itemprop="thumbnail" src="https://whynot.fail/img/notion-18bdeff6-aa7d-436f-a55b-b8bbdcc9c074-012E6354-B620-4723-B799-772BCB9B01A5.jpeg" alt="Me writing a blog post with vim"/> </p> <h1 id="existing-solutions">Existing solutions</h1> <p>There are some UIs built specifically for git enabled static sites like <a href="http://forestry.io">forestry.io</a> but all of them lack the support for custom pieces of markdown (also known as <a href="https://gohugo.io/content-management/shortcodes/">shortcodes</a> in the <a href="https://gohugo.io">hugo</a> world). This makes the actual blog posting experience harder, as your general view of the content is quite different to what the user will consume.</p>

I’ve been searching for a way to write blog posts through a beautiful, mobile-friendly interface for almost two years.

Notion was always a very good answer but the code required to make it work was always keeping me back. But I finally did it, this blog’s content is now fully hosted in Notion

Me writing a blog post with vim

Existing solutions

There are some UIs built specifically for git enabled static sites likeforestry.io but all of them lack the support for custom pieces of markdown (also known asshortcodes in thehugo world). This makes the actual blog posting experience harder, as your general view of the content is quite different to what the user will consume.

There are also blog engines such as Wordpress orghost.org but I didn’t want to manage yet another service, give my data to yet another company or pay yet another subscription.

💡Ghost is probably a very good solution as it’s something between a CMS and static site generator. I didn’t go that way though

The last solution was to useNotion.se as a content editor and generate the actual pages with Hugo through a GitHub Action, as I already do. I already use Notion, Hugo and GitHub separately so no new company or technology was needed to get in the way. Just a little bit of python glue to make them kiss

Announcing notion-markdown

There are two things that needed to be bridged:

  • Notion content → Markdown
  • Trigger a blog rebuild when I edit content through Notionnotion-markdown does the first part and does it quite well. It’s a simple python script that needs almost no external dependencies and takes a Notion page that includes a database as an argument. First, it proceeds to write its properties as a JSON object at the start of the target file and then to translate its content blocks to markdown.

The only thing missing right now (for my needs at least) is gallery support, as it’s a database on its own.

I’m sure there are a lot of blocks missing but I just don’t use them (mainly weird collection views and external blocks). If you’re missing something, open an issue on GitHub or, even better, open an MR.

I decided to use the API that notion uses to render its front end in the web interface, as otherwise I’d have to use the extension API and hassle with secret keys etc. I just hope that the front end API does not change without a notice all the time.

TODO

The current state is very pleasant to me and I’m very proud for what it achieves. Maybe in some time I’ll implement the following too, as they would be nice to have:

  • Watch the target Notion Collection for changes and trigger the build action
  • Short-lived staging environment (maybe with authentication) using the 30’ timeout in GitHub Action runner that builds drafts too
  • Trigger staging build at every Notion Collection event
  • Support Notion comments (and maybe sync withutteranc.es?) That’s all, I’m just too excited to share the news! 🎉
Making PCBs at home: Milling the first layer (and why you need it)https://whynot.fail/factory/making-pcbs-at-home-milling-the-first-layer/Sun, 05 Sep 2021 00:00:00 +0000https://whynot.fail/factory/making-pcbs-at-home-milling-the-first-layer/<p>For the past 5 years I’ve been obsessed about finding a super quick way to make hobby-grade PCBs at home. The race I was looking to win was the “I don’t want to wait 3 weeks being able to do nothing after I remembered that I2C needs in-series resistors”. I want to get my board in my hands in about an hour without doing much.</p> <p>And I found the way, but most importantly, I found the workflow. Let me show you!</p>

For the past 5 years I’ve been obsessed about finding a super quick way to make hobby-grade PCBs at home. The race I was looking to win was the “I don’t want to wait 3 weeks being able to do nothing after I remembered that I2C needs in-series resistors”. I want to get my board in my hands in about an hour without doing much.

And I found the way, but most importantly, I found the workflow. Let me show you!

First of all, in case you missed the title, my solution is CNC milling. The upfront cost is quite budget friendly (less than 200 euros), no nasty chemicals are involved and you can safely toss that awfully bad “PCB drill” out the window. The process takes about 30’ of which 5 are manual labor (preparing gcode and toolchanging)

Required tools

While not on the “simple” side, the tools that are required are cheap and can sit on your workbench.

  • A CNC. Almost any CNC. If you’re a cheap fuck, a CNC 3018 will cut it (I recommendthis). The requirements for the CNC are the following:
  • Some way to hold the copper clad safely on the CNC - clamps/screws/whatever
  • A 60° 0.1mm-0.2mm endmill to mill the traces (I recommendthis set of 10 at 0.2mm)
  • A 1mm PCB endmill to cut the board and milldrill (called fishtail? I recommendthis set)
  • A set of PCB drill bits bellow 1mm (there are many on bg)
  • Some single sided copper clad - just make sure it fits on your CNC (source it locally or through bg) The CNC costs ~250 euros and the consumables ~30. You can find even cheaper CNCs but the sainsmart is quite common and has a community. It’s bad as it is (you won’t be cutting aluminum anytime soon) so you definitely want some people to help you. CNCing is generally hard - apart from PCBs, PCBs are easy and hassle free.

Software Preparation

You’re gonna need the following software setup and working:

  • pcb2gcode - to generate G-Code from gerbers
  • bCNC - G-Code sender that has autoleveling feature
  • The gerbers of the board you wanna make - these should have all the traces on theBACK side

Workflow

The whole idea is the following:

  1. Create gcode from gerbers after some setup (speeds & feeds). The gcode is split in the following files:
  2. Loadback file on bCNC
  3. Connect the probe leads to the cutter and the board
  4. Zero X & Y so that the board fits on the stock and Z roughly 2mm above the board
  5. Set Z 0 (again) in the origin by going toProbe tab -> Probe, ConfigurePos: 0, 0, -3 and pressProbe button. The spindle will start going down very slowly until it touches the board. PressZ=0.
  6. Without lifting the Z, go toAutolevel button and press theZero button with the crosshairs.
  7. Lift Z to ~5mm and go back toProbe tab -> Autolevel
  8. Start autolevel probing by:
  9. Start the cut
  10. After it’s finished, load thedrill file WITHOUT saving changes to previous file and WITHOUT deleting the probe mesh (it pops up 2 questions that you should both answer with No) and change the tool
  11. Go to XY origin, wipe a bit the point under the cutter and do a regular probe to set the tool’s offset and setZ=0 after the probe touches
  12. Start the cut
  13. Repeat steps 10-12 for milldrill and outline
  14. Profit! To avoid breathing all the fiberglass cut you can have a small syringe filled with water and squirt some as the cuts go. It really helps keep everything super clean.

Another idea is to squirt some WD-40 or cutting fluid during the cut - I haven’t tested it but it sounds pretty good and maybe WD-40 isn’t conductive (so you don’t have to wipe it during probing for tool changes). An idea byJames.

Configuring pcb2gcode

pcb2gcode requires some configuration to generate correct G-Code for your setup. This can be done either with a gazillion command line flags or through a file, calledmillproject that has to be on the same directory that the pcb2gcode command is executed. Here is a thoroughly commentedmillproject for my machine:

millproject

# Pcb2GCode settingsmetric=true # Use mm to read the following values (feeds/speeds/etc.), not imperial inchesmetricoutput=true # Same, but for the outputzero-start=true # Start from 0,0,0zsafe=1 # Safety heightzchange=5 # Height to change a tool - don't over-do it to avoid crushing your Z axissoftware=custom # We're not using Mach or LinuxCNCmirror-axis=1 # Mirror the design to X. Required for the back side# voronoi=1 # (optional) Instead of cutting straight traces, cut the board only in the places that shouldn't connect with each other. Produces very weird boards but it's quite fast and optimal# Milling - Trace engravingzwork=-0.07mm # Depth of engraving - did quite a lot of testing and it seems 0.07 is quite consistentmill-feed=600 # How fast to go, in mm/min - maybe go a bit faster?mill-speed=10000 # How fast to rotate the spindle in RPMmill-diameters=0.30mm # Caluclated by pcb_mill_calc.py - 0.30mm for 0.2mm 60 degree endmillisolation-width=0.55mm # Space between traces - I recommend higher than 0.5mm to be MUCH easier to sold and avoid bridgesmilling-overlap=20% # How much should the passes to create the isolation width overlap - 20% is good# Drillingzdrill=-1.7 # Depth to drill a hole, +0.1mm than the board thickness to have clean holeszmilldrill=-1.7 # Same but for milldrilldrill-side=back # Drill the board from the back sidedrill-feed=25 # Lower Z during drilling at 25mm/s - don't go much higher, CNCs don't like drillingdrill-speed=10000 # How fast to rotate the spindle in RPMdrills-available=0.3mm,0.4mm,0.5mm,0.6mm,0.7mm,0.8mm,0.9mm # Available drill diameters - You "should" have all the diameters smaller than your milldrill bit, if you don't have one it will be rounded to the colsest one you havemilldrill-diameter=1.0mm # Diameter of the milldrill endmill - I suggest 1mm as you have much less toolchanges and it lasts quite longmin-milldrill-hole-diameter=1.0mm # Minimum diameter to milldrill - should be the same with your milldrill diameter# Outlinezcut=-1.7 # Depth of cut for the outlinecut-side=back # Cut the board from the backcut-feed=200 # How fast to cut the board in mm/min - can go a LOT faster I thinkcut-vertfeed=25 # How fast to plunge into the board - don't go much highercut-speed=10000 # How fast to run the spindle in RPMcut-infeed=0.85 # Do the cutting in multiple passes, 0.85mm each - maybe this isn't neededcutter-diameter=1.0mm # Diameter of the cutter - use the milldrill bitbridges=4 # Width of each tab to avoid flying PCBs after the outline is donebridgesnum=2 # Number of tabszbridges=-1.2 # Z height while cutting tabs, -1.2 will result in 0.4mm tabs - 0.4mm is ok# GRBL shenanigans# G64 is not supported by GRBLnog64=true# https://github.com/gnea/grbl/issues/290nog81=truenog91-1=true

While the engraving bit is lets say 0.2mm, you’re cutting 0.07mm lower than the surface so the resulting cut will have a bigger width than 0.2mm. To calculate the effective width of cut I created a python script:

pcb_mill_calc.py

#!/usr/bin/env python3import math# For an example of angle=60 tip=0.2 and depth=0.1 check: https://www.calculator.net/right-triangle-calculator.html?av=0.1&alphav=60&alphaunit=d&bv=&betav=&betaunit=d&cv=&hv=&areav=&perimeterv=&x=97&y=22defcalculate_effective_width(angle, tip, depth=0.1): rads= math.radians((180-angle)/2)return2* depth/ math.tan(rads)+ tipif __name__=="__main__":import sys angle= float(sys.argv[1]) tip= float(sys.argv[2]) depth=0.1try: depth= float(sys.argv[3])exceptIndexError:pass print(f"For the tip with{angle} degree angle,{tip}mm tip and for a{depth}mm depth of cut, the following effective width should be used:") result= calculate_effective_width(angle, tip, depth) recommended= result+ (0.05- (result%0.05)) print(f"\t{result} -> rounded up to 0.05mm (for best results):{round(recommended,2)}")

Usage:python3 pcb_mill_calc.py <bit angle> <bit diameter> <depth of cut>

For example to for my 60° 0.2mm endmill withzwork 0.07mm:

python3 pcb_mill_calc.py 60 0.2 0.07

And I get the following result:

For the tip with 60.0 degree angle, 0.2mm tip and for a 0.07mm depth of cut, the following effective width should be used: 0.28082903768654766 -> rounded up to 0.05mm (for best results): 0.3

Oof, that’s it! That’s the hardest part but it needs to be done only once - you can then copy the file around in projects and tinker it a bit.

Generate the G-Code

The rest is quite easy, execute the following command:

mkdir -p /tmp/gcode&& pcb2gcode\ --front"/tmp/gerbers/${PROJECT}-CuTop.gbr"\ --front-output"/tmp/gcode/${PROJECT}-front.ngc"\ --back"/tmp/gerbers/${PROJECT}-CuBottom.gbr"\ --back-output"/tmp/gcode/${PROJECT}-back.ngc"\ --drill"/tmp/gerbers/${PROJECT}.drl"\ --drill-output"/tmp/gcode/${PROJECT}-drill.ngc"\ --milldrill-output"/tmp/gcode/${PROJECT}-milldirll.ngc"\ --outline"/tmp/gerbers/${PROJECT}-EdgeCuts.gbr"\ --outline-output"/tmp/gcode/${PROJECT}-outline.ngc"

It expects gerbers exported by KiCad (due to theCuTop naming convention and the rest) to be under /tmp/gerbers and a variablePROJECT with the name of the KiCad project. If you have indeed a KiCad project, I have an even better command that usingKiKit, generates the gerbers and feeds them to pcb2gcode automatically:

export PROJECT=${$(ls *.kicad_pcb)%.kicad_pcb}&&\ kikit export gerber"${PROJECT}.kicad_pcb" /tmp/gerbers&&\ mkdir -p /tmp/gcode&&\ pcb2gcode\ --front"/tmp/gerbers/${PROJECT}-CuTop.gbr"\ --front-output"/tmp/gcode/${PROJECT}-front.ngc"\ --back"/tmp/gerbers/${PROJECT}-CuBottom.gbr"\ --back-output"/tmp/gcode/${PROJECT}-back.ngc"\ --drill"/tmp/gerbers/${PROJECT}.drl"\ --drill-output"/tmp/gcode/${PROJECT}-drill.ngc"\ --milldrill-output"/tmp/gcode/${PROJECT}-milldirll.ngc"\ --outline"/tmp/gerbers/${PROJECT}-EdgeCuts.gbr"\ --outline-output"/tmp/gcode/${PROJECT}-outline.ngc"

Continue to Step 2 from Workflow and you’ll be done in minutes!

The End

This was quite a journey for me and it took me about 2 years to finish this workflow. Takes about 30’ to make a small board, it’s almost free. The cutters don’t wear much, copper clads are dirt cheap and widely available even in local stores. The boards turn out amazingly well with almost no post-processing required - maybe some flying copper hair.

I’m already preparing the workflow for a double sided PCB workflow, most probably using a spindle camera (it’s cheap, don’t freak out). Stay tuned.

What I haven’t figured out is how to apply solder mask. It needs a weird spring-loaded tool that is able to remove 0.01-0.02 material. If you have any cool ideas, leave a comment!

Alternative PCB making methods

This is a list on ways to make PCBs at home and why I chose milling over everything else:

  • Toner transfer with iron
  • Plotter marker (have a plotter with a permanent marker on bare copper clad, there’s an awesome guide by Stavroshere)
  • Laser engraver (Photosensitive board that is marked by the laser)
  • CNC Milling

Troubleshooting

I wanna keep this section up-to-date with problems that I stumble upon. If you have any problems, even machine-specific, please leave a comment.

Even after leveling, I get uneven traces that are too deep or shallow

First of all, make sure that you didn’t press the smallAutolevel button. What this does is apply the autolevel offsets a second time so the result is just like if you hadn’t leveled your workpiece - but from the opposite side

Then, check that your probe wire doesn’t pick up noise from the motors or spindle. You can check this but doing some movement with your machine and watching if a[P] will randomly show in the machine status. If you have this problem readGrbl Wiki on the matter. Based on that I’ve createdthis board that has 4 optocouplers to isolate the limit switch circuit from the rest of the controller. Worked wanders for me

Clear nrf52 saved BT bondshttps://whynot.fail/notes/clear-nrf52-saved-bt-bonds/Wed, 28 Apr 2021 00:00:00 +0000https://whynot.fail/notes/clear-nrf52-saved-bt-bonds/<p>Often the nRF52 micros get stuck or misbehave and reach a weird state with the pairings. Often the solution is just to clear them so here’s adafruit’s code to do that and a <a href="http://platform.io/">platform.io</a> ini to make it easy.</p> <p><code>platformio.ini</code></p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-Bash" data-lang="Bash"><span style="display:flex;"><span><span style="color:#f92672">[</span>env:clearbonds<span style="color:#f92672">]</span> </span></span><span style="display:flex;"><span>platform <span style="color:#f92672">=</span> nordicnrf52 </span></span><span style="display:flex;"><span>board <span style="color:#f92672">=</span> particle_xenon </span></span><span style="display:flex;"><span>framework <span style="color:#f92672">=</span> arduino </span></span></code></pre></div><p>The board can be any nrf52 board, it can be any generic board that uses the same chip that you actually have. For example <code>particle_xenon</code> uses nRF52840, so it can be used for any 52840 board. It might though not flash the correct LEDs, so just hook up the serial port.</p>

Often the nRF52 micros get stuck or misbehave and reach a weird state with the pairings. Often the solution is just to clear them so here’s adafruit’s code to do that and aplatform.io ini to make it easy.

platformio.ini

[env:clearbonds]platform= nordicnrf52board= particle_xenonframework= arduino

The board can be any nrf52 board, it can be any generic board that uses the same chip that you actually have. For exampleparticle_xenon uses nRF52840, so it can be used for any 52840 board. It might though not flash the correct LEDs, so just hook up the serial port.

src/main.cpp

/********************************************************************* This is an example for our nRF52 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution*********************************************************************//* This sketch remove the folder that contains the bonding information * used by Bluefruit which is "/adafruit/bond" */#include<bluefruit.h>#include<utility/bonding.h>voidsetup() { Serial.begin(115200);while (!Serial ) delay(10);// for nrf52840 with native usb Serial.println("Bluefruit52 Clear Bonds Example"); Serial.println("-------------------------------\n"); Bluefruit.begin(); Serial.println(); Serial.println("----- Before -----\n"); bond_print_list(BLE_GAP_ROLE_PERIPH); bond_print_list(BLE_GAP_ROLE_CENTRAL); Bluefruit.clearBonds(); Bluefruit.Central.clearBonds(); Serial.println(); Serial.println("----- After -----\n"); bond_print_list(BLE_GAP_ROLE_PERIPH); bond_print_list(BLE_GAP_ROLE_CENTRAL);}voidloop() {// Toggle both LEDs every 1 second digitalToggle(LED_RED); delay(1000);}
Dry your filaments in the drawerhttps://whynot.fail/factory/filament-drawer/Tue, 26 Jan 2021 00:00:00 +0000https://whynot.fail/factory/filament-drawer/<p>This is a weekend project to keep your filaments safe &amp; dry. It’s very easy to rebuild and adapt to your needs with (hopefully) available spare parts.</p> <p>After a long term abusive relationship with the 3D printing hobby, where I was brutally murdered several times as described <a href="https://whynot.fail/factory/things-that-went-wrong-with-my-ender-3/">here</a>, it was finally time to find a good partner and settle down. I bought the Original Prusa MK3S. I can finally print dickbutts using plastic. The printer just works, there’s nothing more to add.</p>

This is a weekend project to keep your filaments safe & dry. It’s very easy to rebuild and adapt to your needs with (hopefully) available spare parts.

After a long term abusive relationship with the 3D printing hobby, where I was brutally murdered several times as describedhere, it was finally time to find a good partner and settle down. I bought the Original Prusa MK3S. I can finally print dickbutts using plastic. The printer just works, there’s nothing more to add.

1a1ff1fb-250b-48bc-a1aa-fe6da47cb05c.jpg

Prusa holding a poker face after the Ender 3 told it what it went through

But getting through so much, I can now fully appreciate my printer and do the best I can to keep it happy and a big part of that is to buy good quality filament (I use Prusament and Devil Design) and keep it dry (around 20% humidity and below 60C, for almost all filaments and materials).

How to keep the filament dry

There are many ready made solutions to keep your filaments dry. Either purpose-builtfilament dryers or generic vertical food dehydrators to dry a filament before use or after misplacing it inside your pool, but they don’t take care of the permanent/long term storage.

There are also filament containers, which take care of storage as well. This is the most used type as you just set the target humidity and forget it. Of course there are bothready made storage solutions andDIY.

Dehydrating filament boils (hehe) down to more or less the following building blocks:

  • Moisture absorbers (silica gel, the small non-edible salt packs that you get with electronics)
  • Heat - just heat it up and moisture will evaporate
  • Dehydrator - no idea how they work, so I’ll market it as “magic boxes that lower humidity”
  • (There’s also vacuum that I just learned at the time of writing but not at the time of project planning. More info:https://www.youtube.com/watch?v=eqQRN9TUw08) I wanted something that integrates with my lab (no random plastic containers here and there) and be dirt cheap with stuff I had around - I had just spent a lot on a new printer and my lab starts to seem like a garbage disposal place from the various random parts I’ve collected over the years for “future projects” - lets make this one of them. So it’s set, I’ll build something on my own.

What do we have around

The printer was laying on a perfectly sized nightstand and it was a very good fit. The filaments were placed on the first drawer and random prints awaiting use as well as some spare parts were sitting on the second drawer. I just needed to somehow create a controlled climate on the first drawer.

My target was to use as much “building blocks” as possible (aka have around), so heat & silica gel.

Silica gel requires no further explanation - as packages from all over the world arrive at your house, you’ll gonna build a big stock of them and never run out.

For the heat part though, I took an interesting turn: Use the small heatbed I had when I tried to make adelta printer and then spent thousands in therapy for PTSD.

The electronics to control the heatbed was the easiest part - I instantly knew I’d use one of the thousands ESP8266 WeMos Minis I had lying around (I had no need for WiFi or the horsepower, but it’s a buck each and I had thousands), with a DHT22 temperature & humidity sensor and probably a screen to have a view on what’s going on

So the plan was the following:

  • Make the temperature/humidity controller using the ESP
  • Install the heatbed and wire it to the ESP
  • Throw in silica gel bags

Building the climate controller

For this recipe you’re going to need:

  • WeMos Mini
  • DHT22 temperature/humidity sensor (the white one, the blue is garbage)
  • PCD8544 screen (Nokia 3310 screen)
  • Some wire
  • (optionally) WeMos Dual Base Lego time! 🙂

3 minutes later I had both my debugging and (almost) finalized hardware. Yey!

6ab1063c-a8a3-4b36-83a0-584a05bed0b2.jpg

Lego for adults

At this point I should point out that you can use the exact same components but not in “WeMos mini shield” form and use a breadboard, solder on protoboard or evenmake a board with your 3d printer, but I wouldn’t go that way. Just buy a bunch of WeMos shields from aliexpress for a couple of euros each and never go back. It’s fun!

I should point out that for no apparent reason, my obsession kicked in and I “had” to make a shield for the 5V voltage regulator (I wanted to feed from the same 12V line that I was gonna feed the bed) and a “backpack” shield on the relay that breaks out 2 pins to connect the bed thermistor to. I don’t know why I didn’t use a breadboard. My overengineering could not be tamed.

Programming the climate controller

Another cheat mode I used in this project apart from WeMos isESPHome. I love this lil fella!

ESPHome is a firmware for the ESP family that transforms it to an IoT device. It’s the programming equivalent of Lego (TM) for sensor-based projects in YAML. Definitely check it out - it’s easier than you think and it does not need (but is able to talk to) any other home automation services, devices or bridges.

I say that it’s a cheat as there’s no need for WiFi capability per-se (although it’s nice to watch the humidity on your phone) but I didn’t NOT want it and ESPHome made the whole project much easier and give the ability to program/update it over the air for free (as in beer, freedom, time, the boobs and the rest). Noice.

The resulting YAML I used (reading the thermistor was a tad tricky and I was stupid enough to lose the forum link that explained it):

esphome:name:filament_drawerplatform:ESP8266board:d1_miniwifi:ssid:"Hello"password:"*****"# Enable fallback hotspot (captive portal) in case wifi connection failsap:ssid:"Filament Drawer Fallback Hotspot"password:"**********"captive_portal:# Enable logging# logger:# Enable Home Assistant APIapi:password:"***"ota:password:"***"font: -file:'slkscr.ttf'id:font1size:8 -file:'BebasNeue-Regular.ttf'id:font2size:30 -file:'arial.ttf'id:font3size:12sensor: -platform:dhtpin:D4model:AM2302temperature:name:"Filament Drawer Temperature"id:filament_temphumidity:name:"Filament Drawer Humidity"id:filament_humupdate_interval:1s -platform:ntcsensor:heatbed_sensorid:heatbed_tempcalibration:b_constant:3950reference_temperature:25°Creference_resistance:100kOhm# - 100kOhm -> 25°C# - 1641.9Ohm -> 150°C# - 226.15Ohm -> 250°Cname:HeatBed Temperature -platform:resistanceid:heatbed_sensorsensor:heatbed_sourceconfiguration:UPSTREAMresistor:100kOhm -platform:adcid:heatbed_sourcepin:A0update_interval:neverfilters: -multiply:3.3switch: -platform:gpiopin:D2id:ntc_vccrestore_mode:ALWAYS_OFFinternal:True -platform:gpiopin:D1id:heatbed_powerrestore_mode:ALWAYS_OFFinterval: -interval:0.2sthen: -switch.turn_on:ntc_vcc -component.update:heatbed_source -switch.turn_off:ntc_vcc -interval:1sthen: -if:condition:lambda:'return id(filament_hum).state > 20 and id(filament_temp).state < 50 and id(filament_temp).state > 5 and id(heatbed_temp).state < 52 and id(heatbed_temp).state > 5;'then: -climate.control:id:heatbedmode:AUTOelse: -climate.control:id:heatbedmode:'OFF'climate: -platform:bang_bangid:heatbedname:"HeatBed Controller"sensor:heatbed_tempdefault_target_temperature_low:28.5°Cdefault_target_temperature_high:30°Cheat_action: -switch.turn_on:heatbed_poweridle_action: -switch.turn_off:heatbed_powervisual:min_temperature:20°Cmax_temperature:50°Ctemperature_step:0.5°Cspi:clk_pin:D5mosi_pin:D7display: -platform:pcd8544reset_pin:D0cs_pin:D8dc_pin:D6update_interval:2scontrast:70lambda: |- it.printf(18, 0, id(font1), "Filaments"); it.printf(14, 4, id(font2), "%.1f%%", id(filament_hum).state); it.printf(0, 34, id(font3), "%.1f°C", id(filament_temp).state); it.printf(42, 34, id(font3), "%.0f°C", id(heatbed_temp).state);

Assembly of the drawer

So? Did it work? How well?

It actually did! And pretty well! I wouldn’t want to change any humidity controlling related stuff. Here are some numbers and graphs to make you believe me:

untitled.png

Yey! Graphs and timelines!

Above you see that as soon as the heatbed temperature raises (top red) ambient temperature humidity falls (bottom red). Top blue is ambient temperature - must be kept below the glass temperature of the materials inside the drawer - in my case 60C for PLA & PETG.

What I might fix at some point is to remove the upper wood lip to allow me to sit the filaments vertically - right now they’re sitting horizontally and I can fit 4 of them.

Another thing I’d like is to swap the relay with a mosfet to avoid that clicking sound - most times I don’t even hear it but it would be neat, and as I’m at it design a proper 12V->5V shield.

Things that went wrong with my Ender 3https://whynot.fail/factory/things-that-went-wrong-with-my-ender-3/Wed, 07 Oct 2020 00:00:00 +0000https://whynot.fail/factory/things-that-went-wrong-with-my-ender-3/<p>Why is it that hard to 3D print across years? Why can’t I have consistent printing experience, while not spending a kidney? I don’t get it. Why is the machine constantly failing? I’m a computer guy, I know that human errors are all over the place but how does a machine break on its own so frequently. And don’t get me wrong, it might be a budget Creality Ender 3 but it’s proven to be a good machine and its components are not majestic. This is me… sad…</p>

Why is it that hard to 3D print across years? Why can’t I have consistent printing experience, while not spending a kidney? I don’t get it. Why is the machine constantly failing? I’m a computer guy, I know that human errors are all over the place but how does a machine break on its own so frequently. And don’t get me wrong, it might be a budget Creality Ender 3 but it’s proven to be a good machine and its components are not majestic. This is me… sad…

It’s not often that I’m deeply sad about technology. Most times I’m angry and I do dirty or too opinionated jokes about the subject and I’m feeling better. But at this point, I’m just sad. Today my printer broke again and I have to spent half its cost to fix it. I just want it to do what it was supposed to do, not something else, not hack it, not do it super fast or majestically. I just want to print plastic stuff for fun.

This pupper is too reaching for its plastic toys

A list of things that went wrong

  1. After my first 2 prints, the bed clipper got caught on the right side of the frame, the stepper started skipping and the board was deep fried like a McNugget, one LCD wire was glowing orange for a moment. Result: LCD dead, board resuracted (too many hours)
  2. Couldn’t get BLTouch clone work with Marlin as it had a bug or something? Result: Countless hours debugging
  3. Bed mesh generated with BLTouch was not in effect during printing - G28 was ruining it. Result: Countless hours debugging, went to Klipper
  4. A bit of plastic got into the hotend fan (not the part fan) and it stopped. The hotend overheated and the teflon inside it got too hot. Result: Got to undo the hotend and replace the teflon tube
  5. My raspberry pi (OctoPi) had some undervoltage problem (while being powered directly from a PC PSU), octopi was lagging and the prints were failing. Results: Many random failed prints, went to a proper x86 full blown server that was hanging around
  6. BLTouch accuracy is inconsistent - might be 0.03mm might be 0.1mm. Result: Countless hours debugging, never found the culprit. Gonna buy a new one from trianglelabs? I’m not paying ~60E for a probe
  7. My X gantry was tilted and first 1-2 layers were sometimes a bit off in the back vs front. Result: Bought dual Z system which is not very good
  8. Extruder started skipping (known Ender 3 plastic extruder problem). Result: Bought an aluminum one
  9. While the bed mesh was calibrating, BLTouch hit on a clipper and half of it came apart (after the rest of the BLTouch problems). Result: Me sad, continued to work exactly as before, even with the same accuracy
  10. At some point, the temperature readings started being bonkers. could be constant 5 C (My room is never below 26). Tried several different thermistors, I think the MCU’s pin is problematic. Result: Me absolutely terrified
  11. After changing server the temperature problem was gone for quite long. But it came back after 2-3 power cycles (printer was unused for 2-3 months), and probably hotend MOSFET got overheated and died - when I turn up the temperature nothing happens, the PSU fan does not get noisy as it did. Result: Me writing this post and probably getting the SKR miniExpected result of my printer in the next 100 hours of tinkering with it. Send help

Conclusion

After all these, for some reason I still think that Ender 3 is a piece of nice machinery and I suggest to any 3D printing enthusiast to get one. What I do not suggest is getting into 3D printing in the first place. It’s a sad place where your dreams get brutally murdered and your 48 hour long print fails at the last hour or a small fire takes place.

I got the bug though, so I’ll probably continue to have it as a “hobby” - frightened, anxious and sad. I wish you the best of luck.

Rusty Arduino bindings using PlatformIOhttps://whynot.fail/coding/rusty-arduino-bindings/Sun, 04 Oct 2020 00:00:00 +0000https://whynot.fail/coding/rusty-arduino-bindings/<p>Oh Rust, how much I love you… Love at <del>first</del> third sight, like I had with my English teacher. She was ugly but I was 10 and she was a female that stood near me for an hour and talked to me in a soothing voice. That’s what Rust is, ugly but it’s there for you with a soothing voice.</p> <p>On the other side we have C++ that the Arduino Framework is written on. Classes here and there, mixed with C, requiring a 3 day workshop to understand what’s the “standard” way of blinking a LED - hence the headache of each Arduino library taking the matters on their own hands. I hate reading C++ by the way and don’t know how to write it. That’s why I want to just forget about it and just call it from Rust.</p>

Oh Rust, how much I love you… Love atfirst third sight, like I had with my English teacher. She was ugly but I was 10 and she was a female that stood near me for an hour and talked to me in a soothing voice. That’s what Rust is, ugly but it’s there for you with a soothing voice.

On the other side we have C++ that the Arduino Framework is written on. Classes here and there, mixed with C, requiring a 3 day workshop to understand what’s the “standard” way of blinking a LED - hence the headache of each Arduino library taking the matters on their own hands. I hate reading C++ by the way and don’t know how to write it. That’s why I want to just forget about it and just call it from Rust.

I’m gonna usePlatformIO which is the swiss-army-knife for the Arduino Framework - manages libraries, board definitions, toolchains, flashing… Everything that you’d possibly need to write and deploy code to an MCU. Apart from Rust. pio knows nothing about Rust and was never intended to do so.

Now lets make those two KISS, run Rust on MCUs while using the Arduino Framework!

TL;DR: My attempt lives inthis repo. I failed.

HOw hArD CAn tHAT bE?

Me explaining why C++ is so great

What I want to achieve is to be able to calldigitalRead andSerial.println from Rust code that will run on my NRF52. I choose the NRF52 cause I want to build a Bluetooth keyboard with it and Rust has officialTier 2 support for it, unlike XTensa (ESP32/8266) and AVR (ATMega/ATTiny).

First of all, let’s lay down some ground rules on HOW I am willing to achieve that:

  • I’m not re-writing Arduino code - I’m not gonna implement the whole standard library, I have a life to live as well
  • I’m not re-writing Ruststd - see above
  • Automatic binding creation withbindgen - I won’t write a different crate for each and every target
  • At least some basic support for some 3rd party Arduino libraries - such as theBlueFruit that gives me all the core Bluetooth functionality for the NRF52 and is very well maintained
  • Minimum boilerplate so that all this work does not remain a “Blink.rs”
  • Support for targets other than NRF52 with not too much effort
  • Usage of PlatformIO - the only “good enough” build system for the Arduino framework Ugh… That’s not gonna take a weekend, I was sure even when I started this, but I had no idea how the lack of compiler/linker knowledge would hit me. I should have known that a project exclusively around compiler & linkers will hit hard.

The plan to achieve the above was hella abstract:

  1. Generate Rust headers withbindgen
  2. Write a blinky in Rust
  3. Compile the rest of the Arduino framework
  4. Compile Rust to an object file
  5. Link the above two together
  6. Get the firmware
  7. Profit

Aaaaaaand ACTION

Bindgen kinda compiles the header that you pass to it with LVM and generates Rust headers. It’s a marvelous project, but it might miss something. Unless of course it’s C++ code. Then it trips like an LSD overdose.

Bindgen trying to understand why there are globals and classess in a header

After some time around though, I got it, I just passed almost all of the compiler flags that platformio was passing to gcc directly tobindgen. It kiiiiinda worked, in a weird way. WIN!

Writing a Rust blinky was easy (the code ishere). WIN!

Platformio compiles the whole framework when you give it empty source code (main.c). WIN!

I copy-pasted the link command that platformio was using and I added Rust’s compiled object file (which can be done usingthis option). And it worked! WIN!

I got the firmware! I WIN! Profit!

I flashed the firmware and actually, the LED blinked. I was excited as fuck. Somewhere at this point I started writing this post and I’d mark it as build: passing, but then…

Doing all these at once

There’s a reason that I don’t have exact commands of the above steps so everyone can happily write Rust on their little fella. First of all, it’s been almost 2 months that I haven’t touched the project or this draft so I have no idea what I actually did. Second, this did not turn out as a win. While I can blink a LED, there’s almost nothing else I can do.

I started fumbling with platformio to incorporate bindgen execution, Rust compilation and final code linking with just aplatformio run. Then I metSCons. SCons is the build system that platformio uses to put all these bits and pieces together: toolchains, frameworks, compilers, linkers, linker scripts, source code, header files, etc. I tried to manually change variables, redefine functions, and all the good monkey patching that Python can do but it was a dead end. My brain stack pointer was always overflowing, I just couldn’t follow what was done where and why. Nevertheless, I kindadid it. Didn’t have a good time though.

I could build blinky with one command, good.

Too soon…

Doing something usefull

Print “Hello World”. Nope. Never. Not a chance. I needed somehow to export theSerial object from C++ to Rust and callSerial.println. After hours and hours of reading the headers and the source of the Arduino Framework and trying different options to bindgen, I could not do that. Required huge amount of effort.

Any useful API in Arduino is a C++ class so if I wanted to overcome this, I had to write everything from the ground. That’s when I tossed the project.

Conclusion

I don’t get why C/C++ build systems are so complex. I definitely lack deep knowledge, especially in C++, but come on… This is just too much. Even the Makefiles of a project bigger than 1k SLOC don’t make any sense and you need a manual to understand where anything takes place and why it’s done. It’s a shame.

About the C++ vs bindgen fight, there’s not much to tell, I don’t think that there will be a time where bindgen will be able to handle the code that I read. It’s too complex, it’s too human.

Also there are other solutions to write Rust on an MCU instead of this bad idea:

  • Rust Embedded - lacks USB stack for nrf52 and the BLE stack is on it’s very early steps
  • MyNewt Rust bindings
  • FreeRTOS Rust bindings - I don’t see much development and I’m very sceptic
Adding more magic to the Magicforce 68https://whynot.fail/hardware/magicforce-68-reversing/Wed, 27 May 2020 00:00:00 +0000https://whynot.fail/hardware/magicforce-68-reversing/<p>This is a small journey on how I reverse engineered the <a href="https://drop.com/buy/magicforce-68-key-mini-mechanical-keyboard">MagicForce 68</a> keyboard and tried to add bluetooth functionality to it. It’s a small keyboard (68 keys, 65%) and is USB-only (it’s not the smart model). It has a controller that I can’t flash with a custom firmware, so I had to hook wires on it.</p> <h1 id="the-hardware">The Hardware</h1> <p>The first step in determining what I was against, was to at least partially disassemble the keyboard.</p>

This is a small journey on how I reverse engineered theMagicForce 68 keyboard and tried to add bluetooth functionality to it. It’s a small keyboard (68 keys, 65%) and is USB-only (it’s not the smart model). It has a controller that I can’t flash with a custom firmware, so I had to hook wires on it.

The Hardware

The first step in determining what I was against, was to at least partially disassemble the keyboard.

After the 6 screws under the keyboard and removed, the bottom cover is free and can be carefully removed as well (it has wires to the mini-USB connector board, so beware). The nice red PCB is now ready to be destroyed 😈

Pretty simple schematic, hackable to the bone

This is what I collected: It uses theHoltek HT68FB550 MCU -Datasheet - LQFP48 package

It exposes in the 5 pin header (bottom left on photo):

  • VCC
  • GND
  • PA0/TCK1/OCDSDA - Used for debugging
  • Reset/OCDSCK - Used for debugging & programming
  • UDN/GPIO0 - USB D-, used for programming Debugging & programming are different procedures, according to the datasheet, they use different pins. But they refer to a “Holtek Writer” as the programmer AND debugger. I could find only thee-WriterPro. Seems fucked up (no docs, too expensive, not gonna work on linux/open source software, etc.).

It is a classic matrix-diode style keyboard, it gives logical 1 (5V if I remember correct) to rows and reads it from the columns (that way because of the direction of the diodes).

Matrix to MCU pin mapping (Rows: Top to Bottom, Columns: Left to Rigth):

Pin DescriptionPinName
NC42PgDown, PgUp, Insert
NC46Shift…, Up
NC44Tab…, Delete
NC43`123…
NC47Ctr…, Left, Down
NC45Caps…, Right
PinPin DescriptionName
10NC9
34PA0/TCK1/OCDSDALeft
30PD54
14PD1`
7PE28
28PD32
29PD43
31PD65
36PA2/TP3_1/OSC2Delete, Up, Down, Right
37PA3/TCK2Backspace, PgDown
11NC0
26NC=, PgUp
32PD76
27PD21
33PE0/VDDIO7
12NC-, Insert

All LEDs have a common cathode on Pin 39 -PA5/SDIA/TP1_0 and a common anode to Vcc.

These are all the data that I gathered. Also, (spoiler) I ended up desoldering all of the switches to create my own keyboard so I got access to the front of the PCB. It’s empty, but it’s VERY time consuming to remove all the buttons so here are some photos:

The hack

Ok, so now we know what we’re up against. But what now?

The idea begun with my frustration with wires - right, bluetooth. But how?

I had anAdafruit Feather Bluefruit at hand, based on the marvellousNRF52832. I love the NRF52 family, but after a bit of research I learned that the 52832 does not have USB support and does not have a “CryptoCell”, which means a crypto accelerator which mean noBLE Secure Connecttion. The NRF52840 offers all these goodies (while the BLE SC support for arduino isunder development at the time of writing) but I had to spend money before even having a PoC. Let’s get to work with the 52832!

There was a side idea, that apart from the regular bluetooth keyboard functionality to add U2F and/or GPG SmartCard support. So I started searching if anything like this exists

  1. OpenSK: Written in Rust (🎉) but does not support at all the 52832 and Rust support for the NRFs is pretty useless (maybe I’ll revisit this at some point)
  2. QMK support for my microcontroller - nope
  3. Any github project with over 200 commits that is a keyboard implementation for my MCU, preferrably in MicroPython - none
  4. MicroPython that led me tothis and was a no due to the problems with FS & other unsupported features - nope I was forced to write the whole firmware from scratch in Arduino. Ugh… “Δε γαμιεται…” (roughly translates to “Fuck it…” in Greek). I’ll do it. I’ll hook the rows & columns of the keyboard, connectt them to my MCU and control them. I was sure that the on-board MCU won’t interfere (it did) and it’ll work like a charm (it didn’t) and I’ll throw in an OLED as well (I didn’t). But before that, let’s write & test the firmware. Then I’ll solder wires on the PCB.

The test setup - the MCU, a keypad & an OLED

There you go,Plikter. It is comprised of the firmware that runs on the feather and 2 daisy chained shift registers (TI CD4021BE) that read the columns as there are not enough pins on the feather - and of course these are on a custom board whose gerbers you’ll find in the repo - made with a plotter following the etching method described perfectly bystavros. Soldering time!

The outcome

It didn’t work.

I debugged it and I think that the internal resistors on the ports of the keyboard MCU that were connected to the rows & columns were interfering, but I’m not sure.

Anyway, I had a (mostly) ready firmware & hardware for a keyboard and I was too frustrated by flying USB wires on my desktop. I made theSiCK-68, but that’s a story for another time.

Hope you had fun!

MicroPython on Bluefruit NRF52832 with J-Link and openocdhttps://whynot.fail/notes/micropython-on-nrf52832-with-openocd/Wed, 22 Apr 2020 00:00:00 +0000https://whynot.fail/notes/micropython-on-nrf52832-with-openocd/<p>First of all, lets flash Adafruit’s NRF52 bootloader for easier future flashing</p> <p>My J-Link was “Broken. No longer used” - or so the JLink tools said (AKA bought from e-bay). So I had to go to <a href="http://openocd.org/">openocd</a>).</p> <p>Connect the J-Link (or any SWD capable debugger supported by openocd - even an FT232 breakout will do) to the target - I have a Bluefruit by Adafruit.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-Bash" data-lang="Bash"><span style="display:flex;"><span>pip3 install --user intelhex </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span>cd Adafruit_nRF52_Bootloader </span></span><span style="display:flex;"><span>git clone https://github.com/adafruit/Adafruit_nRF52_Bootloader </span></span><span style="display:flex;"><span>git submodule update --init </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span>make BOARD<span style="color:#f92672">=</span>feather_nrf52832 all </span></span><span style="display:flex;"><span>FIRMWARE<span style="color:#f92672">=</span>lib/softdevice/s132_nrf52_6.1.1/s132_nrf52_6.1.1_softdevice.hex </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span>sudo openocd -f board/nordic_nrf52_dk.cfg -c init -c “reset init” -c halt -c “nrf5 mass_erase” -c “program $FIRMWARE verify” -c reset -c exit </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span>FIRMWARE<span style="color:#f92672">=</span>_build/build-feather_nrf52832/feather_nrf52832_bootloader-0.3.2-28-g79a6a0c-nosd.hex </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span>sudo openocd -f board/nordic_nrf52_dk.cfg -c init -c “reset init” -c halt -c “program $FIRMWARE verify” -c reset -c exi </span></span></code></pre></div><pre tabindex="0"><code class="language-callout" data-lang="callout">💡**NOTE**: `nrf5` command was missing from my package manager’s `openocd` and I needed to install the git version! </code></pre><p>Now the bootloader should be flash and we’re able to flash over serial from now on! Lets flash micropython (I advise not flashing master but a stable tag)</p>

First of all, lets flash Adafruit’s NRF52 bootloader for easier future flashing

My J-Link was “Broken. No longer used” - or so the JLink tools said (AKA bought from e-bay). So I had to go toopenocd).

Connect the J-Link (or any SWD capable debugger supported by openocd - even an FT232 breakout will do) to the target - I have a Bluefruit by Adafruit.

pip3 install --user intelhexcd Adafruit_nRF52_Bootloadergit clone https://github.com/adafruit/Adafruit_nRF52_Bootloadergit submodule update --initmake BOARD=feather_nrf52832 allFIRMWARE=lib/softdevice/s132_nrf52_6.1.1/s132_nrf52_6.1.1_softdevice.hexsudo openocd -f board/nordic_nrf52_dk.cfg -c init -c “reset init” -c halt -c “nrf5 mass_erase” -c “program $FIRMWARE verify” -c reset -c exitFIRMWARE=_build/build-feather_nrf52832/feather_nrf52832_bootloader-0.3.2-28-g79a6a0c-nosd.hexsudo openocd -f board/nordic_nrf52_dk.cfg -c init -c “reset init” -c halt -c “program $FIRMWARE verify” -c reset -c exi
💡**NOTE**: `nrf5` command was missing from my package manager’s `openocd` and I needed to install the git version!

Now the bootloader should be flash and we’re able to flash over serial from now on! Lets flash micropython (I advise not flashing master but a stable tag)

git clone https://github.com/micropython/micropythoncd micropython/ports/nrf./drivers/bluetooth/download_ble_stack.shmake BOARD=feather52 SD=s132 FROZEN_MPY_DIR=freeze allpip install --user adafruit-nrfutiladafruit-nrfutil dfu genpkg --dev-type 0x0052 --application build-feather52-s132/firmware.hex firmware.zipadafruit-nrfutil dfu serial --package firmware.zip -p /dev/ttyUSB0 -b115200

Done!

dzervas nrf> miniterm.py --raw /dev/ttyUSB0115200--- Miniterm on /dev/ttyUSB0 115200,8,N,1 ------ Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---MicroPython v1.12-dirty on 2020-04-23; Bluefruit nRF52 Feather with NRF52832Type"help()"for more information.>>>

If you want to play with other kind of firmware (Rust/C/whatever) and you have to flash ELF orhex files, here is a little helper (put it on your.bashrc or.zshrc):

function adafruit-nrfutil-hex(){ port=${1} file=${2}if["$#" -ne2];then echo"Usage:$0 <port> <hex_file>"return1fiif["$(file"${file}" | cut -d' ' -f 2)"="ELF"];then echo"[+] Converting ELF file to hex" objcopy -O ihex"${file}""${file}.hex" file="${file}.hex"fi echo"[+] Generating package" adafruit-nrfutil dfu genpkg --dev-type 0x0052 --application"${file}""${file}.zip" echo"[+] Flashing package over UART" adafruit-nrfutil --verbose dfu serial --package"${file}.zip" --port"${port}" --baudrate115200 --singlebank --touch1200}
Let's Encrypt the house!https://whynot.fail/homelab/lets-encrypt-the-house/Thu, 09 Apr 2020 00:00:00 +0000https://whynot.fail/homelab/lets-encrypt-the-house/<pre tabindex="0"><code class="language-callout" data-lang="callout">💡This whole setup described is deprecated. Cloudflare offers this whole service for free with a much easier setup and 0 maintenance. Reported by an [HN comment](https://news.ycombinator.com/item?id=22838330) (my handle on HN is ttouch). Don’t use what I describe bellow unless you really have a reason not to use Cloudflare. That’s what this blog is about. Failures 🙂 </code></pre><p>That’s what my mother always said when I was little. And don’t talk to strangers. And the cold comes from the feet (so never walk barefoot). I never got it. How the hell do you use proper signed certificates in a private network? Why have a house if you can’t walk around barefoot? Anyway…</p>
💡This whole setup described is deprecated. Cloudflare offers this whole service for free with a much easier setup and 0 maintenance. Reported by an [HN comment](https://news.ycombinator.com/item?id=22838330) (my handle on HN is ttouch). Don’t use what I describe bellow unless you really have a reason not to use Cloudflare. That’s what this blog is about. Failures 🙂

That’s what my mother always said when I was little. And don’t talk to strangers. And the cold comes from the feet (so never walk barefoot). I never got it. How the hell do you use proper signed certificates in a private network? Why have a house if you can’t walk around barefoot? Anyway…

This is my trip on using Let’s Encrypt in a homelab setup on a very limited budget. It should be a fire & forget implementation. I don’t want toscp 20 certificates every 3 months but it has to be a secure implementation as well - exposing the internal services to the internet is a no-go.

A little side note to the readers that are not yet sure why I don’t go to a PKI (aka managing my own CA) solution: That CA can sign ANYTHING, even google.com, so if the CA gets compromised, as long as you don’t notice, you’re on deep shit… That can be solved with theName Constraints extension (limits the domains that a CA can sign to a certain domain or TLD). But then again, where do you keep it? HSMs are pricey. Even then, will you enter the password every now and then? On which machine? Will it be air-gapped? How do you transfer the CSR? Or maybe you set up your own ACME provider (likestep ca does)? Then you will have to harden the whole machine as it’s not air-gapped…

Also mobiles no longer trust user provided CAs. Actually they do, but they do so only for the built-in browser & mail client, so you lose any native app that supports your self hosted services (ex. Home Assistant app).

The idea

This struck me on a Monday night ~4 A.M. while trying to sleep. I was thinking all the things that I explained above. How? Where? For how long?

Thenpoof, out of nowhere: use a whole domain, or a subdomain that points at a DNS server inside my home network, just to prove LE that you own it and use the signed certificates however I like.

I miss Futurama so fucking much…

At that point, I thought that this was kinda abusing Let’s Encrypt, but then again, isn’t that how VPCs work now?

Of course I would have to make my local DNS server “spoof” that domain and make it point to local IP addresses (by hand, can’t trust DHCP clients mess with my certificates…). Well that’s super easy, a DNS server is already running on my network (resolves DHCP hostnames) and I have root access on it (I have anAlix2) so if I’m gonna run all of my services on a single server, I can put a wildcard A record (each service will have its own subdomain).

So I’ll need a dynamic DNS (paid service or if self hosted, yet another moving part). But wait, why set up that shit and not create a VPN tunnel between a random VPS and my server and forward any DNS requests to the VPS to my server over VPN? Bingo! :D

ACME challenges

It’s widely known that ACME can be very challenging when it comes to safe tool usage

Let’s Encrypt is a CA that issues certificates for free AND automatically. It’s really amazing. They did the web a better place!

What they need to know to sign my certificate, is just that I actually own the domain I say I do. Nothing more. But how do I prove such thing?

They use the ACME protocol to certify that I own the sub/domain I request a certificate for. I have to successfully complete a challenge in order for them to verify it’s me. I won’t get into much details - as I actually don’t know the whole process - but there are 3 available challenges (pick 1):

  • HTTP
  • DNS
  • TLS (I have no idea how this works) With HTTP:

Let’s Encrypt gives a token to your ACME client, and your ACME client puts a file on your web server at http://<YOUR_DOMAIN>/.well-known/acme-challenge/ (as describedhere)

With DNS, a TXT record should be hosted containing a random string that LE gave, at a specific subdomain of the subdomain we’re trying to sign (_acme_challenge.<YOUR_SUBDOMAIN>.). The DNS challenge is also the only challenge that has the ability to issue a wildcard certificate (as there’s no way with an HTTP request prove that I’m in control of all of the subdomains, unlike a DNS wildcard record).

For more info about ACME challenges clap (click/tap)this.

Of course nobody wants to move around random strings by hand or create new certificates every 3 months (LE only signs certificate for 3 months max), so there are a bunch ofACME clients that handle all that fuss. I’d just have to reload the certificate every 3 months - or just restart the whole service.

Our setup

Ok, all this sound good (and a bit complicated) but how will I get the green lock on my plex porn cluster you ask? Let me show you, I answer…

Stuff we need:

  • A domain name (or subdomain) - each service will have its own subdomain. For this example we will usehome.whynot.net
  • A VPS (Google Cloud gives you one forfree)
  • An NS record pointing the domain to your VPS
  • IPTables rules to redirect any DNS requests from the VPS to acme-dns (will explain bellow)
  • A local DNS server pointing<service>.home.whynot.net to the appropriate machine(s)
    graph LR; A((internet)) -->|DNS TXT| B[VPS]; C((internet)) -->|wg0| B; C ---|wg0| D[server]; D --- E(Docker); E -->|DNS TXT| F(Docker); F(acme-dns) -->|53| E;
sequenceDiagram   traefik ->> acme: Certificate for wiki.home.whynot.fail   acme -->> letsencrypt: Certificate for wiki.home.whynot.fail   letsencrypt -->> acme: [challenge-string]   acme -->> letsencrypt: do the challenge   letsencrypt ->> root dns: TXT _acme_challenge.wiki.home.whynot.fail   root dns ->> letsencrypt: _acme_challenge.wiki.home.whynot.fail NS [VPS]   letsencrypt ->> VPS: TXT _acme_challenge...   VPS -->> wg0 (server): DNS request   wg0 (server) -->> wg0 (client): DNS request   wg0 (client) -->> home server: DNS request   home server ->> acme: TXT _acme_challenge...   acme ->> home server: "TXT . . IN [challenge-string]"   home server -->> wg0 (client): DNS request   wg0 (client) -->> wg0 (server): DNS request   wg0 (server) -->> VPS: DNS request   VPS -->> letsencrypt: "TXT . . IN [challenge-string]"   letsencrypt -->> acme: [signed certificate] acme ->> traefik: key & signed cert for wiki.home.whynot.fail
Rust, let me share your awesomeness with Chttps://whynot.fail/coding/rust-c-api-pain/Wed, 04 Dec 2019 00:00:00 +0000https://whynot.fail/coding/rust-c-api-pain/<p>Ahoy reader, this is kinda an open letter. But mostly is my desperation in computer font. Rust why don’t you love me? I read about you, I spent nights and days. I fought the borrow checker monster for you. I learned about lifetimes. And you promised two things: - “Systems” language, close to C - Memory safety</p> <p>I just wanna call you via a C binary. I don’t want you to fly. I just wanna love you…</p>

Ahoy reader, this is kinda an open letter. But mostly is my desperation in computer font. Rust why don’t you love me? I read about you, I spent nights and days. I fought the borrow checker monster for you. I learned about lifetimes. And you promised two things: - “Systems” language, close to C - Memory safety

I just wanna call you via a C binary. I don’t want you to fly. I just wanna love you…

But before we get to the chase, lets get to drama. You know how I love backstories (and I’ve been watching How to get away with murder).

The story

The project that all this happend for is not a new idea to me. It boiled inside me for quite some time. I’m referring to mage I started writing it about 6 months ago, when a friend asked me for a stable tool that is able to listen for TCP shells and have TTY support for his OSCP (that’s a story for another day, for more check outnetcatty). Of course I stopped whatever (another project) I was doing and started coding. I was currently into Go, so I went with it. As I was writing netcatty, first of all I lost a huge oportunity to name it netkitty which is way better and second I started spiraling out about what I could actually do. Why only TCP? I can do better!

That’s where mage was born. Mage is a tiny protocol, intended to be encapsulated inside all kinds of transports. HTTP requests, headers, cookies, TCP timestamps, DNS queries etc. What a marvelous idea!

Remember when post-exploitation toolkits & implants communicated with the C2 over TCP or HTTP? Remember when you could feel the earth shaking every time a meterpreter payload exited the final gateway of a target cause a stray UDP connection to a russian server on port 1337 just opened? Remember when the connection would get killed and your server banned after 5’ you got a shell? Well mage is willing to do its magic to stop this madness.

The blue team laughing at your windows/meterpreter/reverse_tcp

The idea is that you generate a binary payload (msf or whatever) and you “wrap” it using mage. By wrap I mean that the mage .so (or .dll) would be injected inside the binary and then binary patch all thesocket.h (orwinsock) calls to use the mage functions (spoiler: “wrapping” is not yet implemented, that’s what this post is about).

The mage primarilly does the following: - Connect to the C2 (completely ignoring the address that the implant wanted to connect to) over whatever protocol you set up during wrapping - Exchange keys with the server (libsodium) - Start encrypted communication with the server (libsodium)

Useful features include chunking, very low overhead, support for out-of-order packet reception (and maybe sometime packet retransmission?)

That’s all good, but I’m still talking about a Go project huh? No…

As any good project, you have to write it at least twice for it to be good. I think I maybe overdid it and rewrote it too fast.Here. I rewrote it in rust. Rust was a much better fit, as it’s much closer to the system, it doesn’t carry a GC and the overal Rust -insert-lang-here interfacing I THOUGHT was easier. If I only knew…

The target

As said, wrapping is not ready. Nor any actually useful transports. Right now the protocol, encryption/decryption, multiplexing and thread channels are ready. To start implementing wrapping, I had to create a libC API. All answers led tocbindgen, a very cool project that all it does is generate C headers, but to use it, you need to create a C API!

The “final” struct that I wanted to export wasConnection (seehere):

pubstructConnection<'conn> {pub id:u32, stream:Stream, reader:&'connmutdyn Read, writer:&'connmutdyn Write, channels:HashMap<u8, Vec<(Sender<Vec<u8>>, Receiver<Vec<u8>>)>>}impl<'conn> Connection<'conn> {pubfnnew(id:u32, reader:&'connmutimpl Read, writer:&'connmutimpl Write, server:bool, seed:&[u8], remote_key:&[u8]) -> Result<Self>...}impl Readfor Connection<'_> {...}impl Writefor Connection<'_> {...}

The C API has to be like that (to be in-place compatible withsocket.h):

#[no_mangle]pubunsafeextern"C"fnconnect(_socket:c_int, _sockaddr:*const c_void, _address_len:c_void) ->c_int#[no_mangle]pubunsafeextern"C"fnsend(_socket:c_int, msg:*const c_void, size:usize, _flags:c_int) ->usize#[no_mangle]pubunsafeextern"C"fnrecv(_socket:c_int, msg:*mut c_void, size:usize, _flags:c_int) ->usize

It does not implement all thesocket.h functions, but I started with the most vital ones.

This is my target, exposeconnect,send andrecv to C and let them handle the whole logic. No mystery threads n’ stuff, it could mess a lot wit AV evasion (while it AV evasion has nothing to do with this project, I shouldn’t make it harder)

The problem

The problem that I quickly realized was that there was no way to have a “state”. I couldn’t just pass theConnection struct back & forth, assocket.h does! I have to adhere to the function signatures and if someone messes with my struct in a completely unchecked manner, anything could go wrong.

So I went on and tried to create a static object holding aConnection, that would be initialized onconnect. Oh the horror…

Rust says that it needs to know the size ofConnection at compile time to let me have it as static. That’s not possible. I add a reference, but it can’t live long enough so I go withBox.lazy_static enters the game. No idea what it does, but it solved a problem with static. But introduces another. No mutability. So I add aMutex.

Right now we have this:

lazy_static! {staticrefCONN:Mutex<Option<Box<Connection>>>= Mutex::new(None);}

Ok, that’s fine. It compiles (nobody knows if this actually works yet). But then starts another rabbit hole. Insideconnect, among other stuff I callConnection::new.Connection::new acceptsreader: &'conn mut impl Read, writer: &'conn mut impl Write. And these are satisified by aTcpStream andTcpStream.try_clone.unwrap(). Now I can’t borrow these, as they’re inside the function scope.

This is the problem. I don’t know how to passTcpStream to a new staticConnection. I tried making it static as well,Boxing andRcing them. Didn’t fucking work. If anyone can help, please do so…

My code after all the “tries”


I know that you don’t read this type of posts often - or I don’t often read them (ranting due to lack of skill). But this was mainly a rubber duck debugging session for me and it’s one of the very few moments that I’m so stuck, that I’m thinking about abandoning the project. Most times I just get bored or find something new. This is different. I’ve hit a brick wall and can’t find even a really dirty hack around it (even though I hate “hacky” code).

Happy Hacking!

Chinese Factory v0.2 - Plastic À La Crèmehttps://whynot.fail/factory/plastic-v02/Sun, 20 Oct 2019 00:00:00 +0000https://whynot.fail/factory/plastic-v02/<p>Take a breath, sit back and think: Why the fuck not spend some money instead of endless, painful hours? You don’t have money ok, ok, but what if you… <em>WAIT</em>. Wow, a new world, 3D printing, ACTUAL 3D printed hollow cubes that I PRINTED. Oh wait, is that smoke?</p> <p>Welcome ladies and gentlemen on another miserable and painful part oooooof <em>drumroll</em> the CHINESE FACTORY!!! Starring: - Tears - Anxiety - A Creality Ender 3 3D Printer kit that I got from gearbest - 1 month waiting - Smokey electronics</p>

Take a breath, sit back and think: Why the fuck not spend some money instead of endless, painful hours? You don’t have money ok, ok, but what if you…WAIT. Wow, a new world, 3D printing, ACTUAL 3D printed hollow cubes that I PRINTED. Oh wait, is that smoke?

Welcome ladies and gentlemen on another miserable and painful part oooooofdrumroll the CHINESE FACTORY!!! Starring: - Tears - Anxiety - A Creality Ender 3 3D Printer kit that I got from gearbest - 1 month waiting - Smokey electronics


This time, once again, I thought I knew, that I learned from my mistakes. If you don’t know what I’m talking about, checkthis out. It was time to buy my first, whole, 3D printer kit. Backed by a very big community, Ender 3 by Creality was a very good shot. Everyone was astonshed by the results that this baby could achieve. Medium printing speed, medium noise, but the object was very nice. I also ordered with it TWO BlTouch clones. Not one (cause I knew), but TWO. Noice.

Me waiting for a month my order to arrive

I saw a couple youtube videos, just to be sure and get some tips, but the build process was pretty simple. They nagged that it lacked a step or two or a screw, but with my experience on the Rostock Mini and the Prusa i3, I couldn’t even get why they were nagging. I had spares of everything: nuts, bolts, motors, drivers, boards, beds. I was fairly sure that as soon as something goes wrong (cause I was FAIRLY sure about that), I’ll be able to replace it. The device even came pre-flashed! I didn’t even have to fiddle with Marlin! What I was missing all these years…

First prints

After I put everything together, I turn on the machine, I select a pre-sliced model and I hit print. AND IT PRINTS. The bed was a bit off. BUT IT PRINTS. I tried not to cry cause that shithole that I called home would flood in an instant and burn my printer.

Ok, everything works, I level the bed a bit and I fire up Cura for some serious (meh) shit: my first useful model. A littleventring to cool the parts all around the hotend. And it prints it smooth as fuck. I just couldn’t believe it… I had a working 3D printer!

Ventring is loading :D

So now, lets mount the BLTouch. I start printing the model, but somehow, I forgot that the silver “ear” of the paper clip holding the bed is open on the left side of the bed. And it gets stuck on the Z axis. And before I know it, the cable connecting the controller to the screen is orange-ish and the controller is smoking a pack of Marlboros…

I turn off everything, I panic and I’m just staring at the black aluminum brick that I had in front of me…

The Controller Fix

I plug the printer again, to see what the damage was: XYZ and the screen were dead. Everything else seemed fine. Thermistors, heaters, extruder, all fine. The screen was completely optional to me, as I ran the printer via USB, so the real problem was XYZ. Debugging was officially in progress…

You can see the “ears” of the clips on the left and right side of the bed - moments before the disaster

I was pretty sure that the stepper controllers were fried. They are fragile and it happens. Problem was that they were soldered on the PCB. BTW, a quick note:

Dear 3D printing community, After I was done panicking and crying over my dead printer, I remembered that I know how to wield a soldering iron. So I found the pinouts of the Creality “Melzi” board and scratched the traces (to expose some copper and solder on it) ofdir &step to break out the pins and hook them on the backup stepper drivers that I had. I quickly soldered a circuit on protoboard (with solder bridges) to have a nice pinout and hooked the board on it.

Nope, XYZ still dead. Ugh…

The logic analyzer kindly explained to me that the pins coming from the MCU, were dead - this happens when you feed weird stuff to AVR (e.g. over 5v). They don’t die, they give away that specific pin, they are very tough…

Well ok, that’s fine, I had a lot of spare pins in the screen connector, now unused. The idea was to remap the step/dir pins to them. That was fairly easy, as I had hooked the whole lanes from the PCB to the steppers, without cutting any traces. After some pain to understand which screen pin is which, I finally did it :) I changed which MCU pins talk to the stepper drivers.

It was alive :)

The Rabbit Hole Exhaustion

After that incident, about a year passed and I don’t know why I left the printer on the side. I had fiddled with it too much, I did stuff that where not neceserry. I tried to switch to RAMPS 1.4, but had problem with the heating elements not heating enough, even after cutting the D1 diode (spoiler: it was the polyfuse), I switched to klipper from Marlin and broke the printer into two boards etc. etc. I didn’t get to print anything at that point. Always something was problematic and didn’t let me print.

The Slap

About a year passes and I get a girlfriend. I tell her that I have a 3D printer that is currently in an unknown state. She was AMAZED and asked me why I don’t fix it. That was it. That was the slap that I needed to get back in track and fix the damn thing. When a partner gets excited about a nerdy thing you don’t let neither the partner nor the thing go. You just hold on to what you do. Until they orgasm. Or until you orgasm. Or both. Or until you finish the project (lol). Anyway…

I ordered a replacement board. Gearbest gave me $50 off and I got a new official Creality board for about 20mor**e.Kindastupidmoveasthepricewasinsan**e(70 for an arduino with 4 stepper drivers), I know, but I couldn’t get back to the rabbit hole again…

I hook it up, I hook up the BLTouch andBOOM. It works… and unbelievably silent. A quick google search showed that I luckily upgraded to TMC drivers that are extremely silent. The only noise was the fans! Wow…

The Happy Ending

After some playing around and overcoming some difficulties: -G28 negates bed leveling, you need a Marlin setting to fix that - Probe X/Y offset settings are not for fun, the bed mesh is shifted - Teflon tube on the hotend goes ALL the way down to the heatblock - PLA pieces can get into the hotend fan and stop it (and we know what that means) - PLA and PLA+ are not the same - Ender 3 plastic extruder is trash - get the aluminum one - Glass bed with carbon finish is amazing - well worth the 20$ - OctoPrint is quite neat & it can send you image notification on Telegram

Example of successful print! :) The design was a bust, but who cares

The printer was actually fine. It still prints very nicely! I’ve print several stuff for home and the GF even got the handle oftinkercad and designed & printed some stuff!

WhyNot.Fail is not only about fails, but for success stories too, as 99% of the time they include massive failures.

Chinese Factory v0.1 - The-Plastichttps://whynot.fail/factory/plastic-v01/Fri, 11 Oct 2019 00:00:00 +0000https://whynot.fail/factory/plastic-v01/<p>All I ever wanted, was a tiny Chinese factory inside my house. I’m not talking about the people, suicidal thoughts or racism against Chinese people, I’m talking about being able to make stuff. Quickly and effortlessly. So, instead of paying a factory and waiting for a month, I’d like to pay 10x the cost and cry myself to sleep, before I can get what I want. But it’s a one time thing :) (per machine).</p>

All I ever wanted, was a tiny Chinese factory inside my house. I’m not talking about the people, suicidal thoughts or racism against Chinese people, I’m talking about being able to make stuff. Quickly and effortlessly. So, instead of paying a factory and waiting for a month, I’d like to pay 10x the cost and cry myself to sleep, before I can get what I want. But it’s a one time thing :) (per machine).

After having so much stuff in mind, it was clear what was the first machine that I needed:angel voices a 3D printer.

Not only I wanted to make several dumb plastic stuff for the house (like a hanger, soap holder, etc.) and enclosures for several hardware projects, but most importantly: make OTHER machines. It’s like the saying: Crack a hash and you’ll pwn 1 machine, learn to phish and you’ll pwn the planet. So, it was clear (although the saying is not), I NEEDED a 3D Printer.

I have had experience with a 3D printer and it was absolutely horrible: Warped bed, 2 broken control boards (!) and more than 200 hours of debugging and never been able to print anything but a 10x10mm hollow box. It was a Prusa i3. What did I learned from that:

  1. How a 3D printer works
  2. EVERYTHING can and will go wrong
  3. Auto bed leveling is not optional
  4. Stepper motors & drivers are rather expensive (most likely the most expensive part on a printer)
  5. Locknuts on heatbed help a lot (to keep it sturdy for longer times)
  6. Only Thor can turn locknuts I thanktolabaki hackerspace for that. I even spent 2 nights in a couch made from old computer cases for that printer (named Pamela), turned out that wasn’t enough, we needed money as well…

So after having learned that, you think I’d have an idea on where to head next, for a successful 3D Printer. A ready kit that it’s proven to work and has a wide community? LOL NO. A FUCKING REPRAP DELTA PRINTER THAN NOBODY HAS EVER HEARD BEFORE. I have no idea how I settled for that thing, really. Maybe the lack of money. The printer I’m talking about isRostock Mini.

You can see the raction of the 3D Printing community for my choice

So, let’s start gathering parts:3DHubs for 3D printed parts and eBay for everything else. Now great ideas started flying… Why get a 5mm carbon rod that the RepRap clearly references? I’ll get a 6mm! Sure it’ll work the same! Order the printer base cut in CNC? Nah, lets gather everything else and I’ll just make some holes on a piece of wood. That fan for the all metal E3D v5 hotend is optional, I’m sure.

Can see where this is going? Let’s break down this disaster…

The carbon rods

As this is a delta 3D printer, it uses some rods to hold the “effector”. The effector is the base that holds the hotend. It needs to be very lightweight, as the motors are pretty far away and the only thing moving the whole construction are GT2 belts. So a good idea is carbon fiber rods. The printer was designed for 5mm carbon fiber rods but I got 1m long 6mm OD carbon fiber rod and cut it by hand.

The rods where not of the exactly same length and 3D printing teaches you that almost everything has to be precise as fuck. But that did not prove as huge of a problem as the reality of 5mm vs 6mm holes for the rods on tiny plastic parts. When I realised that, I tried drilling the holes. But the parts just broke (duh…).

So I went for the second best option: find a solution that does not involve cutting the rod by hand and re-printing the small parts that the rods go in.Kossel, that everybody knows and loves, uses some rods that are metal but are ready to go. Their length was precise, they have bearings on their ends etc. They were 20cm instead of 15cm, but I calculated and saw that I’ll just lose some printing area, that was fine.

Months pass and the rods arrive. YEY! I try to fit them on the effector. NOOOO. They go all over the place, as the bearings are much smaller than the original printed part… Fuck…

So I got lock nuts, to hold them in place. That seemed to work, so let’s move on…

The CNC cut base

I was not able to find a CNC inside Greece and for some reason I didn’t want to use 3DHubs (maybe it had no support for CNC yet?). I thought that I’ll be able to get around it by using a piece of wood and make some holes. NOPE.

3D printing teaches you that almost everything has to be precise as fuck. Uuugh… Some time passes and I finally find a CNC, right in my city, Heraklion. YEYA. I cut the base DXFs in a CNC! YEYA!!! Wait, that doesn’t seem right. The holes are way off. No…

The base is clearly completely disoriented, as well as my workspace

But STILL, I thought that this piece of crap might be able to work, so lets move on…

The E3D v5 “optional” fan

I have everything hooked on RAMPS 1.4, motors seem to work correct, endstops work, heatbed works, hotend works. Lets try to melt some PLA. YEY IT WORKS!

I just play around for some time (less than an hour) and everything goes to hell. I thought that currently I didn’t need the PROVIDED fan that sits on the hotend, as I was just testing… The nut that holds the PTFE (push fit nut?) had melted…

That was the last sign that I needed to let this project to the side, until I get a proper 3D printer as a kit with auto bed leveling and a community to support it…

Till then, I’ll be crying in my shower, see ya!

Abouthttps://whynot.fail/about/Mon, 01 Jan 0001 00:00:00 +0000https://whynot.fail/about/<p>Your next door humanoid with a grain of love for programming, infosec, electronics, martial arts/acrobatics, binge watching series till you can&rsquo;t move. Excited under-engineer (== that&rsquo;s boring, I&rsquo;ll automate it, but I&rsquo;m too bored to automate it) and rational buyer, cause &ldquo;I&rsquo;ll need it for my next project&rdquo;. Here you&rsquo;ll find failed or unfinised projects and maybe, JUST MAYBE finished projects - but don&rsquo;t get your hopes up.</p> <p>I&rsquo;m Dimitris Zervas and this is my blog, hopefuly. Lets hope that this project will fly. That&rsquo;s my hobby, projects about projects.</p>

Your next door humanoid with a grain of love for programming, infosec, electronics, martial arts/acrobatics, binge watching series till you can’t move. Excited under-engineer (== that’s boring, I’ll automate it, but I’m too bored to automate it) and rational buyer, cause “I’ll need it for my next project”. Here you’ll find failed or unfinised projects and maybe, JUST MAYBE finished projects - but don’t get your hopes up.

I’m Dimitris Zervas and this is my blog, hopefuly. Lets hope that this project will fly. That’s my hobby, projects about projects.

For questions/ideas/whatever, hit me up at dzervas at dzervas dot gr or at Exarchia, Athens, Greece (don’t hit me for real, it’s a saying).

PS: I often cry over code that does not work as I imagined or my 3D printer. You’ve been warned.

Have a nice trip!