What's new arround internet

Last one

Src Date (GMT) Titre Description Tags Stories Notes
Blog.webp 2022-06-17 20:19:14 BSidesSF 2022 Writeups: Tutorial Challenges (Shurdles, Loadit, Polyglot, NFT) (lien direct) Hey folks, This is my (Ron's / iagox86's) author writeups for the BSides San Francisco 2022 CTF. You can get the full source code for everything on github. Most have either a Dockerfile or instructions on how to run locally. Enjoy! Here are the four BSidesSF CTF blogs: shurdles1/2/3, loadit1/2/3, polyglot, and not-for-taking mod_ctfauth, refreshing turtle, guessme loca, reallyprettymundane Shurdles - Shellcode Hurdles The Shurdles challenges are loosely based on a challenge from last year, Hurdles, as well as a Holiday Hack Challenge 2021 challenge I wrote called Shellcode Primer. It uses a tool I wrote called Mandrake to instrument shellcode to tell the user what's going on. It's helpful for debugging, but even more helpful as a teaching tool! The difference between this and the Holiday Hack version was that this time, I didn't bother to sandbox it, so you could pop a shell and inspect the box. I'm curious if folks did that.. probably they couldn't damage anything, and there's no intellectual property to steal. :) I'm not going to write up the solutions, but I did include solutions in the repository. Although I don't work for Counter Hack anymore, a MUCH bigger version of this challenge that I wrote is included in the SANS NetWars version launching this year. It covers a huge amount, including how to write bind- and reverse-shell shellcode from scratch. It's super cool! Unfortunately, I don't think SANS is doing hybrid events anymore, but if you find yourself at a SANS event be sure to check out NetWars! Loadit - Learning how to use LD_PRELOAD I wanted to make a few challenges that can be solved with LD_PRELOAD, which is where loadit came from! These are designed to be tutorial-style, so I think the solutions mostly speak for themselves. One interesting tidbit is that the third loadit challenge requires some state to be kept - rand() needs to return several different values. I had a few folks ask me about that, so I'll show off my solution here: #include int rand(void) { int answers[] = { 20, 22, 12, 34, 56, 67 }; static int count = 0; return answers[count++]; } // Just for laziness unsigned int sleep(unsigned int seconds) { return 0; } I use the static variable type to keep track of how many times rand() has been called. When you declare something as static inside a function, it means that the variable is initialized the first time the function is called, but changes are maintained as if it's a global variable (at least conceptually - in reality, it's initialized when the program is loaded, even if the function is never called). Ironically, this solution actually has an overflow - the 7th time and onwards rand() is called, it will start manipulating random memory. Luckily, we know that'll never happen. :) Hack Tool ★★★★
Blog.webp 2021-03-16 16:32:50 BSidesSF CTF 2021 Author writeup: Hangman Battle Royale, where you defeat 1023 AI players! (lien direct) Hi Everybody! This is going to be a challenge-author writeup for the Hangman Battle Royale challenge from BSides San Francisco 2021. This is actually a reasonable simple challenge, overall. I got the idea of using a bad mt19937 implementation (the Mersenne Twister PRNG used by Ruby and Python) from SANS Holiday Hack Challenge 2020 (which is still online if you want to play!), and wanted to build a challenge around it. I had the idea of Battleship originally, but ended up deciding on Hangman for reasons I no longer remember, but that I'm sure made sense at the time. The game When you run the game, it prompts for the number of rounds: $ ruby ./hangman.rb Welcome to Hangman Battle Royale! ================================ MAIN MENU ================================ How many rounds do you want to play? (2 - 16) If you play at least 8 rounds, you win the special prize! When you choose a round count, it picks a bunch of CPU names to build brackets: ================================ ROUND 1! ================================ This game's match-ups are: Meirina Tresvalles -vs- Gelbert Chhangte Kebede Boehmer -vs- Karthic Cassity Mairtin Piedrahita -vs- Winston Pawlowski Brendaliz Lumbang -vs- Josipa Perlow Unusual Ballenger -vs- Carmellia Agregado Jinnie Khalif -vs- Jeegar Madela Vjeran Saltarelli -vs- Rachella Newfield And finally... YOU -vs- Patience Saravana! The vulnerability The actual code powering the list of players uses Ruby's built-in PRNG, which uses a predictable Mersenne Twister to generate random numbers. I don't love how the name-choosing code was a little bit contrived, but it can leak enough state to predict future random numbers: def get_opponents(count) return 0.upto(count-1).map do || i = rand(0xFFFFFFFF) "#{ FIRST_NAMES[i & 0xFFFF] } #{ LAST_NAMES[i >> 16] }" end end Each pair of names is a single 32-bit integer from the Mersenne Twister PRNG. It turns out, if you can leak 624 32-bit outputs, you can recover the full state! That means if you play at least 10 rounds, you end up with 210-1 names, or 1023 32-bit numbers (because you're the 1024th player). Once you've gotten the state of the PRNG, you can predict everything else that's going to happen! The exploit My exploit is super quick and dirty. It can parse the output from the game and grab the seed using mt19937predict: predictor = MT19937Predictor() for _ in range(511): (a, b) = read_names(i) predictor.setrandbits(a, 32) predictor.setrandbits(b, 32) (and yes, this is probably the first time I've ever written a Python solution!) Then does a final validation on your opponent's name to make sure the solution is working: (_, actual) = read_names(i) first_actual = FIRST_NAMES[actual & 0x0000FFFF] last_actual = LAST_NAMES[actual >> 16] final_name_actual = "%s %s" % (first_actual, last_actual) print("Validating...") print(" -> Final name (predicted):", final_name_predicted) print(" -> Final name (actual): ", final_name_actual) assert(final_name_predicted == final_name_actual) And prints out the 10 words that will be chosen: for i in range(10, 0, -1): word = predictor.getrandbits(32) print("Round %d: %s" % (10 - i + 1, WORDS[word & 0xFFFF])) # Waste RNG cycles for _ in range(1, (2**i) >> 1): predictor.getrandbits(64) To use it, I just connect to the game and tee the outpu Hack Prediction ★★★★
Last update at: 2024-05-20 01:08:03
See our sources.
My email:

To see everything: Our RSS (filtrered) Twitter