the inky void
37 subscribers
20 photos
3 videos
24 links
deranged mamblings of a madman
Download Telegram
Channel created
Channel photo updated
Competetive programming > ctf

Contrary to what you might think I am, in fact, a ctf player and not a terrible one at that, though not really exceptional either. However I now realize, that I made a wrong turn in life and should have done competetive programming (reffered to as cp from here on out) instead of wasting 2 years playing ctfs. I will note, that I might underestimate my skills, and a competetive programmer reading this might underestimate theirs. Anyway here be reasons:

- While playing ctfs, I came to rely a lot upon googling and inneficient or premade solutions for most problems. And it's not that I can't come up with a solution myself, it's just that I expect these tools to be at my disposal. I won't be writing a prime number test, when gmpy2 has is_prime, for example. I also can afford to wait 2 hours to get an answer. This is great for real life work, but it isn't that hard and if you get used used to it too fast, you will lose a lot of experience and knowledge in the aformentioned algorithms.

- Skills gained by playing ctfs are practical in nature and are not uniq to them: system administration, googling, development and finding bugs are things you learn while programming in general. Skills gained in competetive programming are. If I had not played ctfs for the past 2 years and instead done competetive programming, I would be no less of an expert in linux, low-level programming and various technologies, but I would have been far better at algorithms and related math. I would be less of an expert in reverse engeneering and binary exploitation sure, but it's not something most people are interested in, even in the ctf community, or that is hard to learn outside of ctf. (i.e. through pwnable.kr, pwnable.tw, pwnable.xyz, reverseveryday.com and others)

- Cp allows you to easily enter the best universities of your country, while ctf doesn't even give pocket change. Even if you don't care for your education, studying in a good university is still better, because you won't surrounded by brainlets and that one guy like you, who played ctfs or did robotics.

- Cp is generaly better excepted by HR and in general. An ICPC winner will generaly be better regarded than a DEFCON ctf winner, even though the later is far harder and a far better display of practical skills. And that assumes you want to work in infosec, because otherwise ctfs are pretty much useless for hiring. And even in infosec a lot of people view ctfs as stupid games.

- Ctfs were at first open competitions, later brought down to the college and school level, with competetive programming being mostly the other way around, neither transition was complete though. So school ctfs are few and far between, most people get into ctf in college and it isn't hard for a competetive programmer to do so maybe even later in life, compared to a ctf player, like me, trying getting into competetive programming in college, especially with the small amount of competitions for students, that I'm aware of, and the difficulty of most of them.

Now ctfs of course do have their advantages, like being able to play from your machine, having completly customised it, the aforementioned practicalaty of the skills gained by playing ctfs, the variety of tasks and categories or just being a far more interesting and diverse game, but I don't think they change anything, since as I explained, it isn't hard for a competetive programmer to do ctf, with the reverse not being true. I have thought of leaving ctf altogether and... I won't. probably. Jumping between cp and ctf will just make me good at neither, but still. It's sad to bury dreams. I definitely recommend doing cp over ctf for anyone under 20. In fact I'm not sure I recommend ctf at all. All it gave me was useless skills, dissapointment and false confidence.
😒2
telegram-cli is the worst command line tool that I am aware of.

What I wanted: a simple shell command to write a message and send a file through telegram, given nickname and msg/file.
What I got: a lot of suffering and pain.

Starting the app, you get promted with your number, then the code you were sent and that works fine. You might get your dialog_list, send a couple message message through msg and that works fine too.

You might think that now you can simply just use the -e option to send a message in a shell command, but no, than doesn't work. replacing nickname with @username doesn't work either. Why so? Well, you can't just send messages to anyone, only those from dialog_list. This excellent architectural decision also means you can't start a new dialog with telegram-cli. The -e executes a single command before exiting, so you can't add dialog_list to the very beginning.

Maybe use the lua api? Two problems: it doesn't forward argv (it does forward stdin though so it's easy to just send arguments as zero terminated strings) and every function just fails abd, perhaps it was went to used with the daemon, but thats not clearly stated in the docs.

As it turns there is an option (-W) to send dialog_list, wait for it to output and then execute whatever, so I used that.

But the pain never doesn't end here. Remember how I said some things worked fine? Thats not entirely true, because sometimes dialog_list randomly fails with an assertion error and on macos that happens always, this can be fixed by restarting and rebooting sometimes. It also crashes if you don't have internet and with some filenames. The golden standart of stability and reliability.

Another issue is with spaces in filenames, they can't be opened, if qouted. The solution here isn't immediatly, so its necessary to inspect the sources (which require a 32-bit compiler to make for some reason, so it can't be compiled on macos, because it doesn't support 32-bit binaries anymore). telegram-cli depends on a lib called tgl (as I understand it was initially written by the author of telegram-cli, forked and then developed some more). In this excellent library tgl_do_send_document calls _tgl_do_send_photo to send any document, so you know its good. Its poorly documented c code with far too little abstractions and a terrible architecture. Public functions can take easily take 10+ arguments, the few comments that are there are either pointless statements for some automated system (like /* {{{ Profile name */ and /* }}} */), out-of-context note to self or commented out peaces of code, there are lines of code longer than 350 characters, structures are build by hand, rather than in functions. Anyway what source of the problem is in the aforementioned _tgl_do_send_photo, which calls wordexp(3) and uses the first word in we_wordv as the filename presumably to expand ~ -> $HOME, so of course if there is a space in a filename, it will split it into 2 words. A lib of course shouldn't expand ~, that should be done by the client application, but there is a simple a way to fix this. Just put the name in double qoutes with backslashes, like '\'file name\''. And yes, it does have tests, the are 68 and 126 lines long.
Some interesting behaviour in python, you might accidentally notice, is:
>>> class A:
... def m(self): ...
...
>>> a, b = A(), A()
>>> a.m == b.m
False
>>> a.m is b.m
False
>>> id(a.m) == id(b.m)
True
At first you might think you're being tricked and id just doesn't actually return a unique identifier, but no id just returns the address of the argument object:
https://github.com/python/cpython/blob/00d7abd7ef588fc4ff0571c8579ab4aba8ada1c0/Python/bltinmodule.c#L1170
Indeed debugging shows that the address of a.method is the address of b.method, but they're different objects, even on the memory level tp_self is different in them. How come? There's only one scenario where this could happen: if python binds methods on each access, not on object creation (python creates a.method, gets its id, then destroys it because it has 0 references, then creates b.method at the same address), which turns out to be the truth.
https://github.com/python/cpython/blob/master/Objects/object.c#L1155
Extremely readable code like all of the cpython codebase, but basically what it does is tries to get a method from the type (and mro), if it succeeds and it is a property it binds it and returns it straightaway, if not it gets the dict of obj and searches for the attribute there, returns it if found or if there is not such attribute, but it found a method earlier it binds it and returns it and else it found nothing it raises AttributeError. Thats why you can overwrite methods (and get them back by deleting attributes) it also means you can do stuff like this:
>>> class A:
... def a(self): print("a")
...
>>> a = A()
>>> a.a()
a
>>> A.a = lambda self: print("b")
>>> a.a()
b
>>> A.c = lambda self: print("c")
>>> a.c()
c
>>> m1, m2 = a.a, a.a
>>> id(m1), id(m2)
(140043233937072, 140043239244336)
>>> id(m1) == id(m2)
False
Why? I don't know, I guess maybe you'd want to change the class or its mro is some bizarre world.
People still ask why python is slow, this is why. While php introduces jit in new version, python binds methods at each access.
Some time ago I came across a riddle. What do you think will the following code do?
#include <bits/stdc++.h>
using namespace std;

int ost[] = {0, 1, 2, 3, 4, 5, 6};

int main()
{
for(int i = 0, val = ost[0]; i < 7; val = ost[++i]){
cout << val << endl;
}

return 0;
}
a) print numbers from 0 to 7
b) print numbers from 0 to 7
c) print numbers from 0 to 7
d) print random stuff and the segfault

a|b|c are indeed correct, if you don't compile it with optimizations, but if you do it will indeed crash. The reason why is pretty interesting and took me a while to figure out: basically the last call to operator<< in cout << val << endl is inlined and has a potential throw in its small code, val = ost[++i] is undefined behavior for i = 6 and should not be reached, meaning for the compiler the loop always breaks before the last element is reached, it assumes that the exit is the aforementioned raise and optimizes the loop condition out, as well as putting the throw after the loop and replacing the call with a break.

This behaviour can be reproduced in both c and c++ by replacing cout << val << endl with any function call that will be inlined and can throw exit from the program and any usage of ost (so that the array access is not optimized out), however it is a lot less likely in c (the highest chance for it to show up is near user redefined memory allocations which exit if malloc fails), For a synthetic example
#include <bits/stdc++.h>
using namespace std;

int ost[] = {0, 1, 2, 3, 4, 5, 6};

void mb_exit(int n) {
if (rand() == 1337 + n) {
exit(1337);
}
}

int main()
{
for(int i = 0, val = ost[0]; i < 7; val = ost[++i]){
mb_exit(val);
}

return 0;
}
lol gcc allows (clang doesn't as "this is a complex feature which is infrequently used, so it is unlikely to be implemented anytime soon") to allocate closures on the stack, automatically disabling nx and making the stack executable. Very cool idea that fits into c semantics perfectly. Unfortunately it's too late to build security technologies around it so I doubt it will ever see much use, let alone replace int (*f) (void *, ...), void *arg. All it does is absolutely (ie not via call, but via a constant and register) call the underling function with the pointer to a part of the stack with the closure variables in a register not used by the calling convention.
1 typedef int (*func)(int);
2
3 void make_closure(int n) {
4 int closure(int m) { return n + m; }
5 func f = &closure;
β†’ 6 }
7
8 int main() {
9 make_closure(1337);
10 }
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "a.out", stopped 0x5555555551b1 in make_closure (), reason: SINGLE STEP
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x5555555551b1 β†’ make_closure(n=0x539)
[#1] 0x5555555551d6 β†’ main()
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
gef➀ x/3i f
0x7fffffffe0d4: movabs r11,0x555555555139
0x7fffffffe0de: movabs r10,0x7fffffffe0d0
0x7fffffffe0e8: rex.WB jmp r11
gef➀ x/10i 0x555555555139
0x555555555139 <closure>: push rbp
0x55555555513a <closure+1>: mov rbp,rsp
0x55555555513d <closure+4>: mov DWORD PTR [rbp-0x4],edi
0x555555555140 <closure+7>: mov rax,r10
0x555555555143 <closure+10>: mov QWORD PTR [rbp-0x10],r10
0x555555555147 <closure+14>: mov edx,DWORD PTR [rax]
0x555555555149 <closure+16>: mov eax,DWORD PTR [rbp-0x4]
0x55555555514c <closure+19>: add eax,edx
0x55555555514e <closure+21>: pop rbp
0x55555555514f <closure+22>: ret
the time has come again for me to create a channel. I have recovered most of the old posts, but this time it will be a little bit different. i will try to consistently provide some meaningful content, but with more leeway for short snippets of information, thoughts and mostly music.
the inky void pinned Β«the time has come again for me to create a channel. I have recovered most of the old posts, but this time it will be a little bit different. i will try to consistently provide some meaningful content, but with more leeway for short snippets of information…»
ΠΏΠΎΠ½
thanks for the suggestion
haven't seen that in a looooong time
πŸ‘2
Π° ΠΈΠ· ΠΌΠΎΠ΅Π³ΠΎ ΠΎΠΊΠ½Π° ΠΏΠ»ΠΎΡ‰Π°Π΄ΡŒ красная Π½Π΅ Π²ΠΈΠ΄Π½Π°...
πŸ€”5😒4
> men enjoy the goth girl aesthetic because it represents a woman that is externally consistent with her inner state. that is to say - evil
πŸ”₯2