I have a Windows VM that can has an internet connection that acts as a tunnel into a VPN, and this VM is supposed to share this internet connection with the host. This works perfectly in principle: On that Windows VM, I have a network interface named Outbound which represents the VPN connection, and an interface named Gateway which represents the connection that is shared with the host. I use Windows Internet Connection Sharing (ICS) to provide routing to the Gateway interface via Outbound. For reasons unknown to me, however, this sometimes just breaks and the only way to get it running again is to simply disable ICS on the Outbound interface and re-enable it. Doing this through the UI every time became annoying, so I researched how to do it programmatically. There is [a great superuser answer](https://superuser.com/a/649183/222330) which provides _almost_ all the details you need, but not quite. Do you want to know more?


When you write a lot of Python that is intended to mimic arithmetic that was taken from C or assembly code, one giant advantage of Python sometimes becomes a burden: The integers are arbitrary precision, and the "built-in" wrapping of fixed-width integer types is something that has to be added manually, sometimes a truly arduous process. I recently had a thought about how this can be done in a slightly less agonizing way. This is a prototype and might require some more extension in the future, but I am pretty happy with it already. The idea is to implement a decorator that will use Python's ast module to add a bitmask to each arithmetic operation that occurs in the code of a decorated function. Here's the code:
import ast
import functools
import inspect


def masked(mask: int):
    '''
    Convert arithmetic operations that occur within the decorated function body in such a way that
    the result is reduced using the given bitmask. All additions, subtractions, multiplications,
    left shifts, and taking powers is augmented by introducing a bitwise and with the given mask.
    '''
    def decorator(function):
        code = inspect.getsource(function)
        tree = ast.parse(code, mode='exec')

        class Postprocessor(ast.NodeTransformer):
            name = None 
            def visit_BinOp(self, node: ast.BinOp):
                node = self.generic_visit(node)
                if not isinstance(node.op, (ast.Add, ast.Mult, ast.Sub, ast.LShift, ast.Pow)):
                    return node
                return ast.BinOp(node, ast.BitAnd(), ast.Constant(mask))
            def visit_FunctionDef(self, node: ast.FunctionDef):
                node = self.generic_visit(node)
                if self.name is None:
                    node.name = self.name = F'__wrapped_{node.name}'
                    for k in range(len(node.decorator_list)):
                        if node.decorator_list[k].func.id == masked.__name__:
                            del node.decorator_list[:k + 1]
                            break
                return node

        pp = Postprocessor()
        fixed = ast.fix_missing_locations(pp.visit(tree))
        eval(compile(fixed, function.__code__.co_filename, 'exec'))
        return functools.wraps(function)(eval(pp.name))

    return decorator
With this decorator, you can now write:
@masked(0xFFFF)
def test(x: int) -> int:
    return x * 0xBAAD
This will leave all code exactly as it is except for the binary operations involving addition, multiplication, subtraction, left shift, and computing powers - all of these are converted to having one additional bitwise and operation on top.


I'm known for my Ghidra stand-up comedy routines. In order to make them enjoyable for everyone in the room, the font size better be not as tiny as it normally is when you do your day-to-day reverse engineering. There are two places to consider: 1. menus, dialogs, etc. 2. specialized components like the assembly listing view and the decompiler # Font Size Override The first can be adjusted by editing the launch.properties file, which is normally located in the support directory within your Ghidra directory (C:\Users\born\Programs\ghidra_11.0.1_PUBLIC\support\launch.properties on my machine). Just add the following somewhere in the file to adjust the font size to 23:
VMARGS=-Dfont.size.override=23
# Components In order to adjust the font size in dialogs, I recommend searching the settings dialog ("Edit" -> "Tool Options") for "font". By the time of writing this involved the following entries (I use 12 for small and 18 for presentations): * Byte Viewer * Console * Decompiler -> Display * Graph -> Program Graph Display Options -> Miscellaneous * Listing Display


This blag post covers scanning the Ghidra virtual memory with YARA. Do you want to know more?


This is a quick one: If you are living in Germany but enjoy using a US keyboard layout — for one reason or another — I recommend using the EU keyboard layout instead. Do you want to know more?


NSQ is an awesome and extremely simple distributed message queue. You can simply use it by publishing messages — that is arbitrary text, I often use JSON — on a so called "topic". A second process can than attach to a topic to consume messages on a so called "channel". Each messages is forwarded into each channel (at least once). This blag post covers deployment of NSQ in the simplest scenario: one box running everything. Do you want to know more?


Assume you did all the proper and mature building steps for your Symfony application. You have a build environment independent of your development environment. You really made sure all the environment variables like COMPOSER_NO_DEV and NODE_ENV are set correctly without getting the double negatives confused. And you execute composer, yarn, and whatnot with all the good switches like --no-dev, --frozen-lockfile, and --production. But you still get the following error message:
Attempted to load class "WebProfilerBundle" from namespace "Symfony\Bundle\WebProfilerBundle".
Did you forget a "use" statement for another namespace?
Then you _might_ have forgotten to set APP_ENV="prod" on the **production system**. It of course makes sense when you think about it. But it always does, once you figured out. Anyway: I hope this helps a fellow traveler at some point in the future! ❤️


Just a quick blag for my future self:
FOR row IN coll
   FOR entry in doc.array
      FILTER entry.field_name != @field_name
   LIMIT @limit
   RETURN DISTINCT doc
Didn't give me what I wanted. While slapping DISTINCT on the RETURN fixed the problem of "I'm getting the same document over and over again" it now doesn't return @limit many documents but seemingly a random — but lower — number. What's actually happening here is, that the indentation is deceiving: the last two lines should be indented one more.
FOR row IN coll
    FILTER POSITION(doc.array[*].field_name , @field_name) == false
    LIMIT @limit
    RETURN doc
Is what I _actually_ wanted. Edit (2023-04-18): And _now_ I learned that you should actually do this:
FOR row IN coll
    FILTER @field_name NOT IN doc.array[*].field_name
    LIMIT @limit
    RETURN doc


The official documentation on ArangoDB usage in Symfony is [literally from 2013](https://www.arangodb.com/2013/03/getting-started-with-arangodb-and-symfony-part1/) and hence targeting a pretty old Symfony version. This blag post will cover adding minimal ArangoDB support by hand. The actual database protocol and interacting will be handled by [ArangoDBClient](https://github.com/arangodb/arangodb-php). Show me what you've got!


If you want to perform SOUNDEX similarity searches with Doctrine in Symfony, you first need to define it as a so called "DQL User Defined Functions". Resources online are a bit dated so I decided to publish this quick blag post. That _sounds_ nice, show me more!


When creating invitations to Discord servers – or "guilds" how they seem to called internally – you can configure some limits. For example, you can limit the number of times a link can be used to join a server or you can configure an expiry date. The default setting for the time limit is 7 days btw, which is why most links are expired when you come back to them after some time. I was in the situation that I wanted to invite a limited number of people to a Discord server and each should only receive a link that can only be used once. So in some sense, I wanted to create personalized invite links, which doesn't seem to be a use case that's supported out of the box. So let's use Python!


I recently played around with scraping public Telegram channels and finally want to do something with the data. In particular, I wanted to play around with Named Entity Recognition (NER) and Sentiment Analysis on the content of the Telegram posts. I think this will probably work much better when you do it for each language separately. So before we answer the question "what's this post about?" or "how angry is the person in the post?", let's answer the question "what language is the post in?" first. And we'll do it while warming up with that hole machine learning (ML) topic. Be aware: I have no idea what I'm doing. Do you want to know more?


This blog post will cover my audio setup on Windows. It's core component is called VoiceMeeter which is a virtual audio mixer for Windows developed by Vincent Burel under the company label "VB-Audio". This blog post will focus on the fact that it makes virtual microphones and virtual speakers available which in turn can be used by all program running on your computer. Do you want to know more?