What's new arround internet

Last one

Src Date (GMT) Titre Description Tags Stories Notes
Blog.webp 2023-04-24 00:08:44 BSIDESSF 2023 Rédactions: Sortez (Difficiel Inverse Engineering + Exploitation)
BSidesSF 2023 Writeups: Get Out (difficult reverse engineering + exploitation)
(lien direct)
This is a write-up for three challenges: getout1-warmup getout2-gettoken getout3-apply They are somewhat difficult challenges where the player reverses a network protocol, finds an authentication bypass, and performs a stack overflow to ultimately get code execution. It also has a bit of thematic / story to it! Writeup Getout is based on a research project I did over the winter on Rocket Software\'s UniData application. UniData (and other software they make) comes with a server called UniRPC, which functions very similarly to getoutrpc. My intention for the three parts of getout are: Solving getout1-warmup requires understanding how the RPC protocol works, which, as I said, is very similar to UniRPC In getout2-gettoken, I emulated CVE-2023-28503 as best I could In getout3-apply, I emulated CVE-2023-28502 but made it much, much harder to exploit Let\'s take a look at each! getout1-warmup The warmup is largely about reverse engineering enough of the protocol to implement it. You can find libgetout.rb in my solution, but the summary is that: You connect to the RPC service You send messages to the server, which are basically just a header, then a body comprised of a series of packed fields (integers, strings, etc) The first message starts with an integer opcode: Opcode 0 = “list services” Opcode 1 = “execute a service” Once a service is executed, a different binary takes over, which implements its own sub-protocol (though the packet formats are the same) For getout1-warmup, you just have to connect to the service and it immediately sends you the flag. On the server, it looks like: int main(int argc, char *argv[]) { int s = atoi(argv[1]); packet_body_t *response = packet_body_create_empty(); packet_body_add_int( Vulnerability Prediction ★★
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