 All right let's do it. Okay make sure we're streaming. Are we streaming? Are we live? Hello. Let's like take forever. There we go. Link should just be automatic. Don't you guys think? Yeah, wait not yet. I'm getting into it. Okay, great. Everything's going. All right. Hello everyone. Welcome to Wednesday. I had some very unfortunate news to share with everyone. You are all slacking on the extra credit. This is the NSA Code Breaker Challenge. Look at that. 71 on the list of schools. Four of you have completed test zero. That's great. 11 of you. Four of you have completed test one. Amazing. Let's get those numbers up. Get that extra credit. Beat the University of Arizona at least. There's 700 of you. Average. You can't average based on this. Now that that's over. People have questions? You? Yes. Yeah, we're gonna finish that today. Are you excited for that? Yes. Yeah. You want to know the World Cup winner, right? Awesome. Cool. We'll definitely do that. Yes. Louder. How do we do the extra credit that we talked about? It is on the course. It is in the syllabus. We talked about it on Monday, so you can go check out that recording. But we have, yeah, we added the NSA Code Breaker Challenge as an extra credit. So follow these steps. Four people have already done it correctly and added me as a follower so I can see the progress. So go to these steps and crush everyone else. Yeah. Go fired up. Guess not. Okay. Cool. Okay. But first, before we go back and finish our World Cup challenge, we are going to finish and talk about, yeah, why we want to reverse engineer and what are some examples of reverse engineering? So you've been doing this, right? You've been learning about how to look at programs dynamically through GDB. You've looked at how to statically analyze programs. So one of the key things that you will be doing in the reverse engineering specifically challenges that you're doing is you're trying to guess the license key. So you're trying to reverse engineer what is a valid license key in that binary. So the checking logic is all baked into that binary and you need to derive what input, working backwards, what input can pass this license check. And this was a real skill and a real thing that happened. So if you think does anybody remember an age before the internet or is this all? We were born after the internet. Well, I'm just asking maybe some people. I knew a guy in my PhD who was from Nepal and had to hike three days to a village that had electricity. And so his first time using a computer was at college. So people have different backgrounds. Also, I don't remember how old you are. So it's hard for me to do that math in my head. So it's easier to ask. Okay. Awesome. Great. Now that I feel like a caveman. So back in the day, before there was internet access everywhere, or before you could even assume that everything had internet access, you had to be able to install software. And the software had to check if you had a valid license or not. Usually the license would be on the box, or you could buy license keys. Windows was famous for this. You had to have a key in order to install Windows like with Windows XP. And so how would they do this without access to the internet? So if you have internet, how would you do this license check? Let's say you're building this software for a company that's hired you, they're paying you a lot of money. How do you do it? Yeah. So keep track on some database somewhere on your system. And then when they install, you put in some license key that then goes and checks with the back end database and say, does this license key have access? You may also do things like, how many times has this key been activated before? And maybe reject it if it's too many. So yeah, you could do this with the internet. But if you didn't have that, you have to have other ways of doing this. So what they did was they, a lot of companies, and you could actually, we'll get into crypto. And there are ways that you can kind of do this with crypto. But a lot of companies didn't bother with that. And they would just take in input, perform some secret algorithm that performed computations on that data. And then that way, it would validate the result. And this way, the company could generate keys that would pass those results, where it would be difficult for pirates or other people who are trying to get access to the software without paying to do. The entire point of what we're doing and what you're learning is that what you put in binary code is not safe and is not secret. So this is, hello. So this is something that you have to understand about binary code. There's nothing secret or safe in there. You can, people can always figure out in reverse engineer what's there. So this gave rise to a group of people who are able to reverse engineer and understand these algorithms. And also the rise of KeyGen software where you could just generate keys that would pass checks. Here's a cool, actually recognize some of these, a WinRaw. So the various different software. So this is software that you find on the internet. These were usually dial up internet. Yeah. So it actually made a WinRaw KeyGen. Everything. Yeah, this is a universal KeyGen generator, Windows 7, a Windows 7 anytime key upgrade, seek and destroy, Nest HQ, Vegas Pro 11. Yeah, we can look at it again. Kaspersky, that's funny. Autodesk. So if you've used like AutoCAD and stuff, because those have a request and an activation, some of them are based on the name. So you put in a name, it would derive some calculation and check that with the key. So this was a whole industry. And if you downloaded one of these KeyGen's, you may also be infected yourself with whatever malicious software they decided that they wanted to run, because you're essentially trusting some random person on the internet to run code on your computer just so you can get some software for free. So let's watch this video. I have no idea what this is going to be about. I didn't watch it. Okay, best KeyGen song ever. Thank you. I have no idea. So if you want to get more into KeyGen soundtracks, then you can, but this specifically, this must have been specifically for this KeyGen software. Okay, that was fun. So there's a whole class of reverse engineering challenges called crack knees. So this is basically a binary that does some check on input and is looking for specific input. And your goal is to generate the possible input, find one input out of all of that that passes checks. This is actually the World Cup thing that we're going to get back to that we did yesterday is a version of a crack knee. And so yeah, you are to think about as you're performing the reverse engineering tasks and the challenges that you're tackling these, you're literally like inheriting this vast array and history of people who are doing reverse engineering stuff. Now there's all kinds of cool stuff that after these KeyGen's became very popular, software developers started thinking, okay, do we really want to have all of this because they're able to easily fix this. So one thing they would do is crack the software. So by cracking the software, you'd figure out how to binary patch the software and change bytes in the program. So like, let's say when it detected a failed KeyGen check, it would rather than jump to the failure case, just jump to the success case. That way anything you typed in would be successful. Or you could legally purchase the software. Very funny. I can't remember which game it was, but there was some game where they released some DRM with the game that would check for your key file. Like if you didn't have a valid key, you could go ahead and play it, but like at level four or five, there'd just be no door to get to the next level and you'd be stuck there forever. So the idea is these pirates that were trying to crack the game, fix the first check, but didn't realize there was a check much later in the game that allowed you to have access. And so people were curiously frustrated at not being able to play games for free. But there's a whole lot of techniques. So the DRM, it means digital rights management. So the idea of how do you control what people do with software that you give them? There's a lot of, it's basically like a cat and mouse game where you come up with some scheme, people break it, new scheme, break it, new scheme. There are all kinds of techniques like anti debugging techniques. How can you tell if somebody is debugging you? As you go through your debugging challenges, you will realize, wait, with the debugger, I have total power and control. I can do whatever I want with this software. And if you're creating some DRM stuff, you would not want people to be able to do anything they want with your system. Another thing is obfuscation. So this is where you take the original code and you obfuscate it in some way to make it much more difficult to reverse engineer. So one technique for that is actually rather than, so you take the X86 code, rather than having the binary have X86 code, you obfuscate the normal program into a different program that interprets the data and executes it on the machine. So you're translating from, if you think about, anybody have an M1, like an Apple Silicon laptop? Yeah. So that has an ARM processor on it that runs ARM binaries. You can still run X8664 binaries because it translates those binaries when you run them from X8664 into ARM at runtime. It's essentially what these programs do. The other thing you can do is actually remove the DRM outside of the CPU. So does anybody use fingerprint readers for their phone or face scanners? Yeah, many people. Yeah. So if you gave me your phone right now, if I hacked your phone, could I get access to your facial scans? No, why not? Yeah. So it's physically somewhere, so it's not on the CPU. It's not in memory. It's in a different dedicated hardware component. So I think Apple calls it the secure enclave. ARM based systems have this trust zone thing where they have things. Guys, thank you. So we have the secure enclave. We have trust zones. The idea is move it out of the CPU so that it's protected by hardware. You can have a lot of secret keys that get there. Yeah. Oh, yeah. It's an idea that's been a long time in the making. I think getting it to the level where it's performance and works well is difficult. Anytime you're doing hardware, if there's any hardware problems, you'll have massive, and you have a security breach, you have massive problems. Cool. Other types of systems for reverse engineering? I think we talked about this with Minecraft last week. We talked about reverse engineering. So people want to modify and change games. They have to reverse engineer to understand how to interact with those games. The good side of this is making things better and making things fun. Back in my day, we played Diablo 2 and you could get Diablo 2 bots that would automatically play the game and go and kill a boss over and over again and just collect the loot. So you'd get a character set that up and just while you're at school, it would go and get loot for you and you'd check the results when you got home. But that was all from reverse engineering to game. Actually, one of the very first times I remember playing with this was the original Diablo. They had some tool that would look at the memory of the process, like any Windows process. And so what you do is look at the memory and you could have a thing to show you what changed. So you look at the memory, use a health potion to see what changed and what got higher and then you could freeze that memory location to that value so you could have infinite health. All kinds of stuff. But the dark side is that people use this to cheat in online games with like aim hacks and wall hacks. All this kind of stuff is all about reverse engineering the game and how it's working. Yeah. So lots of applications for reverse engineering. Questions on that? Yes. Good question. So the question was if somebody obfuscates the code, how do you know that they haven't, let's say, altered it or done it? Like how do you trust that code? I think part of the problem in the part, yeah, you say something. So I think it's more philosophically, we'll talk about hashtags later. I think the key question is, even if they're not obfuscating, how do you know there's not like a backdoor or something in the code? Right? So you'd have to be able to analyze the binary anyways to detect that. But there are ways to do that. But yeah, it becomes more of a trust thing. Right? So it's like how do you, if somebody's, if somebody's giving you a binary, do you even trust them in the first place? And the second place, if it's obfuscated, you have to trust them even more. But this obfuscation is used a ton. A lot of malware uses it, but also commercial software. Like there's commercial tools you can buy and apply on your software system, and they will output an obfuscated binary that is a pain to decompile or reverse engineering. Any other questions about reverse engineering? Yep. Why don't you just ask your questions as I'm transitioning there. Yeah. So the question is, okay, so I'll answer this specifically and we'll get there because whatever comes, we will finish reverse engineering this world binary together. It does not have a ton of those operations in it. So let's let me make sure I have this. Let me bring up my beautiful desktop. 502 back gateway. Always fun. Fun times. There we go. Okay. So I think the key underlying question to your question, right, is, and I've, oops, and I've seen this a few times. It's how do I, so I'm reverse engineering. I'm figuring out what this thing does. Then what do I do with that information? So I've seen some people that do this all by hand that like, we'll use online calculators, they'll reverse things, XOR things. You can find stuff that will XOR things. I, you could definitely do it. You can actually 100% do all of this on paper if you wanted to. You actually don't need a computer for any of this. Some of you are raising your hands. It's slightly terrifying me because you are taking a, what kind of a course is this? A pen and paper course, a penmanship with you guys are missing your feathers and your bottles of ink apparently. Right. There's a computer science course. You can program things. You should use that superpower of programming at any point you can to save you time and effort, including in doing things like performing calculations like that. So my suggestion is to write code that does this. And part of the reason that we, you wrote way back in module one when you were doing web requests with Python is to dip your toe and get familiar with Python. You can use any language you want, but Python is a great language for doing this kind of like one-off little thing. So for instance, if I was demo.py, why is that so big? Let's do this. Okay. So if I was doing something like I wanted to, oftentimes I would define a function. So if I wanted to say like, uh, oh wow, that is really too bad to read, huh? Okay. Okay. No, no window. Let's do a good one. Sorry. I'm trying to remember how to increase the font size. Let's go XOR by three. Is a terrible example function because I'd never hard code something like this. They have a parameter pass to it. But if I said something like 4D in data, so looping through all elements here, I also am going to return something. Let's call it a string for right now equals to a string. And then I'd say something like new character is equal to 4D XOR zero X three. So most languages have the XOR functionality and it performs almost like what you'd expect. You do have to be careful. One of the key things if I have Python and I have 255 plus what's that value going to be? I don't have to say the actual one. It'll be the big, big number, right? Big number. I can keep adding zeros. It'll still be a big number. What if I did this in like C or with assembly with registers? What's the problem I have to think about with registers and see the size, the size of the registers, right? I can only keep track of 64 bits of information. So this is one of the things that can bite you when you're reverse engineering something from a binary and you try to code it in a language like Python. If you're not very clear about dealing with the overflows, but you can actually do this very well by doing something like ending it with, if this was a, let's say a 32 bit number, that'd be what? How many bytes? One, two, three, four. Hey, you lost me. What is it doing? Dude, this thing is like frightening me. No, it's looking at me now, but it was like taking a break. I didn't tell that robot to go take a break. Okay. You can do something like this to limit the results to only be, this would be one, two, three, four. So 32 bits would be the max there by ending it with all ones. You're limiting the results to only be 32 bits. This is a tip that that comes up, but back to our function. So we have a new character. So we take, or gives us the, from a character, the ordinal from zero to 255 of that character x or it with three append it to, but it's an order right now. So I need to call the character function to turn it back into a character. And now I can do things like prints does actually is going to look like, but we'll see. So it's doing it here, a hex dash C, which I showed before to actually look at the hex files. Yeah. So this to the new line. So that's that first string all x or by three. So now I have a function to do this. I could have that function be right past the arguments of what it's going to x or and then I could use that function in order to reverse, which makes things a lot easier and repeatable. Python has a great reverse function where you can reverse a list or a string, which may not, may or may not be handy. Cool stuff. Okay. So we get back to our friend, the World Cup. Any other questions before we dive in there? We have 49 minutes. Do you think we can do it? Shaking your head. Look at how many of us there are. There's tens of people online and all of you in this class. No, we can do it. We have enough knowledge. Okay. We were looking at this in IDA. If I remember correctly, applications IDA. And we're actually exactly back to where we were. Let me take five seconds, font, make the font look bigger, better. Can you read that in the back? Yeah. Cool. Okay. Oh yeah. I remember where we were. See, you know how I know where we were? Because we wrote comments and we defined function names like this is known country name. Right. So we looked at that. That was so groups was our input. So it's first reading in our input for each group groups was a value on the stack. So it's a multi dimensional character. So it's an array of eight 32 bite size characters. And we are so predicting group F gets group I 32. So this is what's reading at most 32 bites into each of those arrays on the stack. We have is known country name. So this checks and this remember went through that group of countries to see and uses string compare to see if that's a known string name or not. If now one thing we will definitely need to do is look at the documentation of stir comp. Anyone know it off the top of their head? Yeah, stir calm. What's the return value? How do we interpret that? So returns an integer less than equal to or greater than zero. If s one is found is less than or is greater than. Oh, this is terribly worded. So it should be so equal to so return something equal to zero if s one matches s two. So it returns zero when they are the same, which is something we need to remember because we're looking at how this is used. So if it's the same, it returns zero. And then this function returns what? So when when does is known country name return one? And when does it return zero? Say it again. So stir comp if group and one of these country names is equal. What is stir comp return zero? So then if not zero would be what true, which is one, which will return one. So the whole function returns one if it's known and zero if it's unknown. Great. Good thing for us to know. Let's also check that this is very clearly an int or a Boolean technically, I wonder if there's a bool type Boolean. There we go. So go back here, file it. I'm low byte. I don't like that. Let's call this an int because that shouldn't that. There we go. Hey, it looks so much better. Okay. So this is weird. So, oh, okay, okay, okay. Great. So is known country name now? When does it return one? When it's in a known name that's in the list and it returns zero if it's not. So if it is in the list, that would be one. And not in the list return zero, which won't do that. So this seems like it's kind of like numb incorrect, or something like that, because it's being decremented every time that it's not in the list. Is that everyone agree? Like kind of there. This is like weird logic. This is where obviously the binary nature of what we're doing something as a one or a zero really shows its face because we had, if you remember all the way down to the depths, we had a string compare, which was returning a zero if they're correct. But then the function that it's calling that returns a one if string compare returns zero. And now we're looking at this and now a string compare or this is known country name returns zero, it will decrement this. So this is a seems like some number incorrect counter. I also don't understand why it's negative, but it is subtracting it in here. So who knows. So what I'm doing here is verifying if the decompilation is correct by going directly to the assembly code, because I know that the assembly code is always the arbiter of truth. Okay. So we actually know like exactly what this is doing, right? Like before we had no idea. Now we know. So now let's check this next for loop. Okay. For J equals zero, J is less than seven, less than or equal to seven J plus plus. So J is going to loop from zero to seven. And it's checking if the string length of groups J is greater than two. So groups was our input. So it's checking if it's greater than two. It is then going. Wow. And it's doing a lot of checks. Okay. Let's ignore this for now, but we'll keep in mind. So what's the next case? Otherwise, num incorrect minus minus. Okay. Let's go forward a little bit. If num incorrect is greater than seven. So we got, but it's also subtracting from num incorrect. This is like super weird behavior. I forgot that this was this weird in this specific instance, but that's life. Sometimes people do weird things. Okay. If it's greater than seven, and then it outputs predict the winner. It's so weird that it did this. F gets into S 32 standard in. Okay. So it's asking us to break the winner. So S is our winner. It's checking that it also is a known country name and the string length of the winner is greater than two. And winner zero is equal to now. This looks more, more simple. What does this check? Yeah. So this is winner is just a character array. So winner zero is the first bite of that. And you all have been looking at ASCII a lot. If I turn this into H in hex by hitting H and turning it into hex, this looks much more like something that we care about and it's ASCII value. And if I, I guess R is the button to turn it into a character. So now we can actually see, oh, this is checking if winner zero is a, who anyone want to guess what this next letter is before we turn into ASCII. R and what's the last one going to be G. Yeah. But it's not even checking the rest, but so it's checking that it's Argentina, right? So or probably like we know that that's a country on the list and we know that it is this ARG. So somebody online is saying maybe num incorrect starts at the maximum number of possible correct. I think that's true except num incorrect here starts at zero. That's what's very weird, which I guess makes sense because you've gotten zero correct, but why would you start at zero and then go around and go negative? It's a very weird way of doing this. I still don't understand the logic of what it's doing there, but this is great. So we've already figured out what to do at least at this stage, right? So we have an idea of what winner that we need to put. We needed to double check that Argentina is actually a known country name and not something else. Okay. Should we try to look? So what's the other bit of code here that we haven't really dug into? Yeah. The whatever it's doing here, right? Of these groups. So okay. How do we break this down? So let's check. Okay. So what kind of looks like when you're looking at it almost like a series of equations. Like V three is equal to not not J and groups zero zero groups. What was groups again? It was our country name, our guesses who would win each group stage. And this is hard coded groups zero zero is 78. Well, what if we look at that as a character capital N? And if groups one one is lowercase n and groups two zero is capital A three one lowercase e four zero five zero two six two seven zero. Okay. So and then looking at the back we can see what's kind of happening here. Num incorrect plus equal v 15 plus v 16 where v 16 is J is equal equal to seven. What's J? What was it? Yeah, the loop the loop increment value. So on the very last one, J is equal to seven and groups J zero is equal to you 15 is 14 plus 13 and 14 is J is six. And groups six two is equal to eight. I think what's happening here. My intuition is, we're doing this loop over it, but then we have like a switch statement in the middle or something that was checking like if J is zero, meaning it's the first element, then check zero zero is N. If J is one, then check one one and how it got compiled and just got compiled into this insane statements for all these things. And then each one is using this and incrementing it and then I think num incorrect is getting added. But on, if we think about it each loop, how many, what values can J have? Yeah, zero through seven. So either J is going to be seven, it'll be six, it'll be five, it'll be four, it'll be three, it'll be two, it'll be one, or it will be not J, which will be zero. So can we get input to pass these checks? Yeah, so we need a country name for group zero that starts with an N. And what about to pass this check? Second group, the second letter starts with a lowercase N. Do we know which names are valid? Yeah. So now we can actually, now we have a plan forward. We need to, if we extract all the country names, then we can write a Python script that goes through the country names and finds one where the first letter is capital N. We can find one where the second letter is a lowercase N. We can find one where the first one is a capital A. We can just use Argentina here, but whatever, like again, like I mentioned, we want to script these things, not just, you know, I don't know, do it by paper. One where the second character is an E and so on. So we have our constraints here. We have our data. We can search through our data for things to hatch and then that will generate input that should pass. And we'll just know for the last one, what should we pass it to predict the winner? Argentina. Cool. All right. So the question should be, how do I get this out of there? Right? Kind of a pain. So there's actually a lot of techniques you could do. One nice thing is we can see here that each character, there's the string, the country name followed by a zero. There's actually all kinds of ways to do this. This is where, I don't know, do you want me to show you some cool editor stuff so I can convince you that Emax is better than Vim? Yeah, cool. Okay. So one trick I've used, you can actually, the nice thing about this is it's just copy pasteable. So I can just copy all of these countries, just this raw text. Maybe we'll do it a couple of different ways. Copy, open up my handy dandy Emax, Emax, rural cup. Do I already have a solve? I like calling them solve.py. The owners like to call them x.py for exploit, but it's more of a reversing. So I feel like solve is better. But let's do that. Okay. Open it up. Okay. So now I have all of the text that was in there in here. Oh no, it doesn't have my Emax set up. We will try to do all this. Okay. Emax has this really cool feature of defining macros of what you're doing. So what I'm going to do is start defining a macro. I'm going to search for the first single quote character, go forward backwards, delete all of that. I will then go to the next single quote character backwards, kill the rest of the line, go to the next line, go to the start of that, end the macro, and then just repeat it over and over again. And then I've got all the countries like this already. Then we want it in Python. So I can go back to the start here. Oops, I keep typing in the wrong character because my keys aren't quite set up exactly with the way I want. But then I can do a similar thing here. Start a macro, double quote, end of line, double quote, comma, space, delete that and then end the macro and just rerun it for everything here. So now I have my countries all here. Kind of cool. So like very quickly, turning it from that list of data into a list like this, you should also be able to, Ida is kind of crazy, I mean, not crazy, but Ida has a lot of functionality. So there for sure is a way to export all this data. Let's see, let's learn together. Export segments. If anybody knows this off the top of their head, aka Connor, export data. There's for sure a way, I just do not recall it. Maybe some file, produce file, dump database type info, none of those. As you can see, I have the way that I do it. So I usually don't look up other ways to do it. Right click, we'll try right clipping, clicking, copy, we just did that. Thank you. That's useless. Okay. I'm gonna let Connor look into that while I go do something else. Where's the thing? Okay. So I'm not that far. Okay. So I have my countries here. I'm going to do a lazy Python script and not worry about a main file or anything. This is kind of one of the things you need to deal with when you're on a time crunch of like a CTF challenge. You're just like, let's go and something up that works. Don't let's not worry about making it beautiful. But as you get burned over and over, you start realizing, hey, maybe if I make it work, not terribly, I won't waste my time when it breaks in the future. Okay. So I need to look for things. I'm again, so I could write something that loops through all of these, looks for something where the first character is an end, the second character is a lowercase end. I could look, I could define that, I could search eight different times. Again, I'm a computer scientist. I don't like repeating myself and just writing the same code over and over. So I'm going to write a function because what am I going to try to do here? Find country by and it will be the character and the offset. Right. So a function and I'm even going to, I just, I guess went on a rant talking about why you wouldn't want to code nicely here. But example, I want find country by if I say n and zero, then it should return like, what's the company that starts with that? Another one's right. So that way I can easily translate each of these constraints into one call to this function. And that way, if I mess up this function of how I'm checking things, I can fix it in one place rather than fixing it in all eight places. Okay. So for C in countries, I guess I can be nicer country in countries. If, oh, sorry, can you see that? If country offset is equal to character. What do I do? What if there's more than one? What was it? Who cares? Why do we not care? We shouldn't just default to who cares? That would be a terrible way to go through life. But why do we not care in this scenario? There's only one check and the check doesn't care if it's the first one, the second one, the third one, the 10th, the 20th check, right? It just is looking for the first check. So return country. What happens if we don't do it? What if we get through all the countries? Should I return try again? This will be super annoying though, because if we don't get it and we just see the string, it'll try the string, we'll try it. It won't work. Why don't we say that we never expect this to fail? I'm going to assert false, meaning that if you ever hit this point, blow up, because I know that something was wrong. Either how I did this function, the data that I gave to this function, or one of my parameters. Because fundamentally, it should never reach this state. If it reaches this state, our understanding of what the program that we were reversing should do is incorrect, or our code is incorrect. But we don't want to get into a case where we return none, or return the empty string, or return something else that will screw everything up. All right, and then let's do... Okay, so we got our cool function, and I just used the Emacs key and deleted that. There we go. Nope, that's not right. Okay, find country. Now, answers. Is that right? Spell grind? Answers? Or is that how I feel like that we're wrong? Did I spell it correctly? Okay, I feel like I've been up here for too long. Either had too much or not enough caffeine. Okay, so we want to find country by N as the zero with character. Other one was lowercase N as which character? Yeah, the offset, I guess I should say, not which character because that's clearly going to mess us up. A as the zero with E as the offset one. That is a three. Keeping you on your toes. It's also a lowercase three, or lowercase E, zero. This may be another case where I'd actually write a macro instead of doing this, so I wouldn't mess this up. That would help us avoid these errors. This is also why this can be very frustrating if you're doing a CTF, and you've been up for 12, 14, 24 hours, and you're making these tiny mistakes, which drive you crazy later. So it's nice to have a lot of the co-coder thing, like the pair programmers, which is like a lot of one-to-many pair programming. B zero, A two, zero, cool. So we calculate that, print it all out. Should we try it? One, two, three, four, five, six, seven, eight. This is going to help us when getting this output into the program. It's kind of annoying because it's in the list and we want to copy paste it. Do we like copying and pasting things? No, because we're hackers. We don't like doing that. So let's go back to our thing. Four A in. Now we're printing it all out. And what was our final answer? Now what if we piped this to the program? Did we just solve this? A, there we go. Got to the successful one. Pretty cool. We just reversed that program. We figured out exactly what input it wanted. And funny enough, did we even care about what that number incorrect was doing? No, because who cares? I don't know. We always gave it correct input. There may be a way we could have given it input that still works. Maybe we just give it the NE or something, but I don't know. Who cares of dealing with that crap if we give it the exact input that it's expecting? And everything works. Okay, great. Somebody said on the Twitch that you should be able to, in IDA, back to our handy dandy data, be able to do shift E. Ah, there we go. Cool. Okay. So let me see here. Shift E for export, I would say. Let's see. Heck string, string literal. Yeah, the problem is these are all like the actual raw bytes, and you'd need to get them into some other form. I wonder if there's a, yeah, somebody let me know if there's a better way to actually, oh, you can do, what was that? As raw bytes, but getting that like into a Python program from raw bytes is kind of annoying, right? So like, oh, raw bytes. Oh, this would be, but it's still have the zero byte in there between them. That's what makes it annoying. But yeah, you can see these bytes, you can get them in there. I don't know why it's not continuing after there. That's weird. So we can save data to a clipboard or if I export it. Yes. Anyways, you'll have to play with it, figure stuff out. Questions? You didn't even think we'd do it in time. We did it way earlier. We were like right there at the end. Let's see. Some tips with reverse engineering. I think one big tip is to, like I talked about getting too deep on things. I'd also say one of the great things about reverse engineering is don't get locked into one modality and only do things statically. We didn't debug anything dynamically, but we could have like, if this num incorrect turned out to be super important, we would have been diving into the debugger, giving it some input, some correct incorrect tracing it, seeing what happens with this value. Frequently, I go back and forth between the two tools. There's a lot of tips. Reverse engineering's great. It can be great and frustrating because the answer is literally right here. There's no special data. There's nothing to guess. It's just like you figuring out this binary of what it's doing and what it's asking for. Any other questions or things you want? Yeah, doing this, but I guess do you want another 20 minutes to work on the challenges? Yeah? All right, good stuff. You're dismissed.