 Hey folks, Adam DuPay here, and today we're going to be looking at the ponable.kr level code map. So this is a 10 point challenge, and so let's dive right in. So it says, I have a binary that has a lot of information inside heap. How fast can you reverse engineer this? So it sounds like it'll be a reverse engineering challenge, and it says, ooh, a hint. Always good to read the hints. See the information inside eaxebx when 0x403e65 is executed, interesting. So you can download this here, there's also an SSH thing. So I've downloaded it here, I've also SSHed, and there's actually an interesting read me here that says reverseengineerthecodemap.exe binary, then connect to the code map daemon, which is running on localhost9021. Hello. And the daemon will ask you some questions, provide the correct answer to get the flag. So interesting. So we want to do this to see what kind of things it's asking us, what is the string inside the second biggest chunk? What's the string inside the third biggest chunk? So we're clearly going to be half to be looking for what is this, what's this program doing? So we can look at it, we'll run file on it. So it actually is in eaxe. So the first thing to check is this file extension.exe, is that a red herring trying to throw us off? So I actually won't be able to execute this on here in my Linux machine or in the... So I actually don't have a Windows machine available now, but let's see, we should be able to reverse engineer this. So I will open up Hopper and I will load up this eaxe here. So it read executable to disassemble, we have our potable.kr and if we have, remind me later, we are talking about code map and there we have our code map.exe. A pretty large program here, seeders, some strings, which are always interesting to look at. These look like strings based on, I wonder if it's a... I'm gonna tell me if it's a executable or not, I don't know, if it's a statically linked. These look like calls into the functions, well, these look good, these are some strings that actually make sense. So again, this is the equivalent of, like we always want to be running strings on these binaries to see what types of things are inside this application and what things could be interesting and what types of things this application do. So if we follow these strings, these are the strings we saw when we connected to the daemon. So what we know is that these are interesting. So these will kind of tell us more about the program itself. So something to logging, so this is in what function, this function, it looks like it's some kind of a main function, does anybody call this? It's called here, stuff happening here, yeah, let's assume we'll call this main for now, we'll call it main question mark, because we don't actually know for certain. We can look at the disassembled view to kind of get some idea where did our functions go. Push, I will make 1000 heap chunks with random size. These should be a print function it looks like, maybe puts is my guess. So I will make 1000 heap chunks with random size. Each heap chunk has a random string, press enter to start the memory allocation. So then call this sub, so this probably is like a read function. Okay, let's go back to the hint. The hint is how fast the reverse entrance. So let's go here, see the information inside eaxebx when this is executed. So if we go back here, navigate, go to address or symbol, so where is this inside of here? Okay, so this is later on inside that function we just are, let's say calling main. So and the hint said, see the information inside eaxebx when this instruction is executed. Okay, 65, 403 e65, 403 e65, okay. So we could do is trace this back and start to look at what is inside eaxebx, what's inside in eaxe. Let's get a feel for what this looks like here. Okay, so this is where it told us to look for things. But let's, I want to get a bigger sense of what's going on here. So we can kind of see the outline here and if we say, so saying we have a bunch of local variables, push ebp, move the stack pointer, so this is a classic prologue that's going on here. Push all f's, push, interesting, push this memory address onto the stack. Do some other stuff, push eax, so move that into eax that I believe looks like a canary, push eax, subtract 54 from the stack pointer, move whatever's there onto eax, xor, ebp with eax. Interesting, I wonder where they're doing that. Let's see is that anywhere, it's just a place. So this does some setup, this should be interesting. We'll need to maybe dig in and see what this does. I will make 1000 heap chunks with random size. Each heap chunk has a random string, press enter to start the memory allocation. So I wonder if this is breaking a, sorry, I wonder if this is break ends up, it's going to be end up breaking the random to see how it's generating these random strings. Cause it says, cause when we executed this, it's asking for, so what is the string inside the second biggest chunk, waiting 10 seconds to prevent brute forcing. So then this, so start, add this, call this, this looks like it's saying press enter to start the memory allocation, maybe this is like a read type function. So this moves ebp, which is zero onto some variable. So it's zeroing out these variables to start and then it's starting this whole process. So let's see var 58 into eax, push eax, pass it to some function, then call another function, then multiply whatever's in eax with eax. One thing is I'll need to look at the calling convention for Windows 32 bit PE, CDQ, move, what is this thing look like. So call that with var 58, ESI, call that function times of by 2710 divide by 539, then call this function with eight as a parameter to get EDI, and then do something with a stack pointer that's kind of weird. That should do nothing. If EDI, if the results of this function is not equal to zero, then do some stuff into here set where EDI is pointing to to 40 F2 EC shift, I think this is a shift arithmetic right. ESI times 2710, one, eight, if EAX, which is the result of this function, which is the same function here, this is not equal to zero, do you have to take EAX plus four, do you have to set take EDX, or just to see what EAXO is the result of this output here. It almost seems like some kind of malloc function. But this is interesting, temp nine, I wonder where this name came from, temp nine is equal to a double dereference ECX called that as a function. So this whole thing just to get in ECX, this function here, oh, maybe I think we did see something about tables, maybe that anyways, call that function modded against 186 AO into temp nine, and set temp nine, oh, this must be a temporary variable that hopper is creating. So temp nine variable five C, five C, yeah, we haven't used yet. Do this thing of the stack that probably doesn't mean anything past that then to this sub 404. If temp nine is greater than or equal to 10, interesting, while EAX is less than is three a e calculator, oops, that did stuff, come up. No, thank you, Siri, I do not want you, I would like just a normal, happy calculator, good. And of course, I touch things, so just change this and, okay, just a nice undo gets rid of all of that. So we know that it's telling us that it's going to do this a bunch of times. So it's doing it, what does it say 10,000 times? So let's see if three E eight, eight, yes, 10,000, okay. So EAX, EAX var 58, so var 58 is basically I is going to be the loop iterator. So that's nice because now we can give that var 58, we can give that a name, we'll call that I, so this will be our loop iterator. Yeah, so I said I equal to zero. And so we're basically going to do this because you can see I plus one is equal to EAX. So it's incrementing it, it's setting it and then it's checking while it's there, it does that. And it does one, two, three, three more things, although it's not picking up. The interesting thing is it's not getting this pushing and then this call that this is a parameter to this. That's okay. The allocated memory size of BiggestChunk is percent D bytes. Oh, this may be stuff to like help us do things. Allocated memory size of BiggestChunk is percent D bytes. I'm going to run this inside wine. Do I want to install that, so we can run this, then we can actually start to try to debug things. Oh, trying to run this on their machine, that's a lot, but that's okay. So we're running inside wine, inside our virtual machine, maybe I didn't want to install staging. Yeah, it's fine. Oh, I can just do wine stable. Okay. Going back to the binary UI. Okay. So basically somehow getting all these values, so it's going to, but what did it say at the very end here? So the allocated size, memory size of BiggestChunk is percent D bytes. Ah, if that's not there, then that is definitely a printf. Push EAX, so variable 54. So dereference variable 54, move it into EAX, push EAX. So that's going to be the size of the BiggestChunk. The string inside that chunk is going to be ECX, interesting, that did not work. All right. So now that wine has installed, let's look at wine and try running this, 2.4 is a testing version, blah, blah, blah, that says I will make 1000 heap chunks with random size. That's great. That's exactly what we wanted. So if the BiggestChunk has a random string, press enter to start the memory allocation. So hit enter. The allocated memory size of the BiggestChunk is 99,879 bytes. The string inside that chunk is this string, log into PonoWolves.KR to get some answers. Cool. Okay. So this definitely, so let's see if this, yeah, so it says random, but this is when it's basically lying to us because we know that this random is not actually random because why we're getting the same value every single time. So now we can run it, which is nice. And so this actually tells us that this variable 54 has the allocated size of the BiggestMemoryChunk. So if we trace that back, we should be able to figure out this value of R54 is going to be the size of the memory that's allocated. And then R60 is going to be apparently that string that's there. Ah, and this makes sense. So if we look up here, far 54, so we'll call this size and we'll call this str. And so we have the size, we have the string. And if we did 65, we'd see this is where it says remember it told us about eax and ebx. So eax and ebx as the size in the string, let's see, how could we do this? See the information side eax, ebx, when that instruction is executed and when we look at this, we see that eax has the size and ebx has the string. So let's see, trying to think what would be good to do here. Okay, let's look at it this way. Maybe, aha. Yeah. So we can see this ESI has this string of the lowercase, uppercase, and digits. So my guess is that it's pulling from here to get these strings. So at this point, I don't really want to actually reverse engineer this binary where in the sense of doing it statically, I really want to do this dynamically because now I have it executing, it's giving me the output. So remember the interesting thing is this is telling us this is the size of the largest chunk and the string inside that chunk. Whereas if we execute this, what's the string inside the second largest chunk? And so we know it's not going to be this answer, right? Because this string is in the largest chunk. And the second answer will be, the second question will be what's the one in the third largest chunk? So we need to figure those out. So my thought process here, what I'm thinking about is essentially, there's a few ways to do this. One way would be to statically go through, understand exactly the algorithm and calculate all those thousand values that it's actually using. I honestly don't want to do that. That sounds like a huge pain in the butt. So an easier way to do what we want to do. And what I'm thinking about now is how can I inject because so there's two ways to do it. Either I can debug. And I debug this binary as it's running in wine. So use wine to debug and to output what are the... So basically what I want to do is exactly here. Every time I get this size in the string, I want it to print out what the size is and what the string is. And if this was a Linux binary with elf, I could easily do that with a GDB script. This is not. I will need to do, come with a different way to do this. One way that I'm thinking about is maybe because I have what I want here. If I can inject code into this function, then I could actually do what I wanted to do. The problem is I'm not exactly sure how to do that in Hopper because you have to worry about all of the offsets here. But maybe I'll explore that. The other option would be figure out how to debug things in wine. Well, when DBG sounds interesting, or wine debug, let's go dash H, wine DBG launch process as if you're starting with wine and run wine DBG on it, potentially a running process of WPI. This actually looks like exactly what I want it to do. Launch process as if we're starting wine and run GDB. This is what I want it to do. Interesting. Attach to running process of wine, WPI, Dnum and run GDB proxy to it. All right. Well, let's try this. So wine DB, I actually really would love to use GDB for this. And the command line is code map.exe. Huh. Okay. Well, what is going on here? I'm not exactly sure. It looks like Jeff does not appreciate being run in this GDB or something. Something here is not exactly right. Let's see. I mean, let's just see what happens if I just continue and it looks like I just killed it. So this is probably a good point to point out that clearly I don't have all the answers and I don't know exactly how to, all these things work. And this happens all the time in a CTF where you have a, here a Windows process. So how do I actually use wine, a DBG, which I've never used before? And maybe I can't end up using this and maybe it'll end up being a pain in the butt. So who knows? It's probably going to be extra, it's probably going to be a generic factory separate points even to symbol code towards a subset. Oh, so I don't need GDB for this. So, 30, I don't know why it's doing that. There we go. All right, reset that bad boy. Let's do this again, yeah, but without the GDB part. Okay, okay, so if it does a subset of GDB, then I should be able to do it. Basically what I want to do is I want to break point here. Fix me heap, RTL set heap information. I guess the question is maybe this binary is anti debugging for some reason. So hopper is the one I want to use. I don't know if maybe this is just being insanely slow or what's going on here. We shall see insert ASM instruction. So I'm looking for anything that has to do with, because I know I can modify the interesting thing, let's see, not region so I can not instructions out debugger, not create string. Let's see. Let's look up what that does first hopper interesting. So apparently Python scripts for use with hopper interesting hopper script assembler to install. Let's see. Do I want to run a just randomly install things and put it into my inter destination this code. Let's see is it going to mess up. Let's see annotation. This is still not doing anything, which is actually the exact same thing that the other Oh, see the question is even if I don't do anything, it basically just straight up does not work. So my thought is this looks like maybe there's some anti debug stuff in here. I could probably get around that. Let's see demango strings. This is simple instruction. So in our brushes, so procedure find C strings generate pseudo code, get relative drafts insert jump that you're not searching invert that's interesting invert a conditional jump. Oh, I know a way we could do this pretty easily. What if okay, so I'll make multiple versions of this. So let's control C this and yeah, okay, I don't know why I didn't think of this before. So basically we have this loop that we're doing a thousand times. And at the end, it tells us what the second largest thing was. I can actually just change this value this O three E eight to O three E seven. And that should print out the second largest value and then change it one more and that should print out the third largest value. Let's see if I can do that. So here, let's think, let's see, I know I can do this in hopper. I've definitely done it before. I think what if I say that this is not this, so O three E eight. So I want to edit this modify, I think I need to put it into like this. Yeah. So what if I do E seven, and then we go back here and we say, aha, there's a new instruction. This is code, compare it with E seven. So this now then I want to produce new executable, code map a second. So this should print out the one right before the end. So I should be able to just use my wine. See seven nine nine eight seven nine wasn't the same one should be comparing EAX to that. Yeah. While EAX is less than three E seven, that's exactly what we want. EAX isn't going incremental. What if I completely change this to like zero zero. Yeah. 3000 hex, which is 768. That should definitely produce new executable on maybe it's because I didn't save it. Try to have no idea this will actually just assemble it. I'm going to go ahead and say no, but let's for this address. Interesting question is why didn't that actually change it significantly? Like if I change this to zero even, I should like completely change this. Executable. Yeah. Okay. That actually makes more sense. Maybe it's because of that big if condition in there. So that's, that's, you can see I changed this code to compare that against. Oh, that turned that into an or. Okay. That's not exactly what I wanted. Oh, I see the three is somewhere else. Okay. Size and that. Okay. Good. You know, I is only touched and incremented in here in this loop. I mean, this I is only incremented once. Oh, maybe here's the thing. It's saying if EAX is greater than size. So, okay. So here EAX comes from this variable five C. This variable five C comes from here, this temp. So this is giving us the size. Okay. So this is giving us the size here with EAX and the idea here, this must be the malloc then of the size. I don't want to go into that, but okay. So I'm understanding it a little more. So the idea was we were only doing it a thousand times, but we didn't actually see when that number changed. We never saw that number change because it only keeps track of the largest and the second largest memory sizes, right? Because it has this check if EAX, the size that it just generated is greater than the size that we currently have, then update the size and the string. So let's see. Can I use this to my advantage? I mean, I could kind of do what I was doing. Let's see. I could do maybe a binary search like a manual binary search on the 1000. So do it at 1000, see what it tells me is the biggest chunk. Do it at, like we already have, do it at 500, then see if that changes it or not. It should change it and then I can kind of keep testing. But that's not, I don't really like that approach. What I really want to do is just be able to print out all of the size and memory or debug it and debug those things. So, but this is pretty interesting. So what about this EBX, this string? So we know the size comes from here, EBX plus F is zero. So that's going to be, so what's the size of this? One, two, three, four, five, six, seven, eight, nine, 10, 11, 12, 13, 14, 15, which is good. So this is zeroing out that last byte and setting EBX plus F, which is 16 to zero. And where is the rest of EBX? So EBX, so this is the memory location, temp 39, so this is the size. So this, okay, so temp 39 is definitely the, this variable 5C is the size. So this is some random function and that's probably calculated up here and obfuscated clearly here. But, so we do that and then we do variable 5C, then we pass that size into this looks like a malloc function. And if temp 39 is greater than equal to, yeah, so only do this if we actually have more than 16 bytes. Take ESI, EDI is variable 50, the address of variable 50, which I don't think is ever used so far. So the address of variable 50, and I'm gonna have to look at the actual assembly here because this doesn't really make sense looking at it like that. Variable 50 into EDI, rep, move SD, I actually don't know what these do. I'd have to look at that like, look in ESI and put something with EDI. ESI, move SW, move SB, XOR, ESI was itself to free it. And we'll look at it here. And then load effective address, move EVs, variable 70. So I pointed up this, let's see, into ESP, that's interesting. So changing the stack and then calling some function. What does that look like here? Call some function, mod 3E minus 50. 3E is interesting. Probably this size ESI plus EBX minus one, all ESI. Okay, so this is probably getting random junk, getting random letters from here. Okay, so we have the size, we know they're keeping the size. And what do I want to do? Let's see, could I programmatically make a thousand versions of this? Yes, I could probably do that. I really wish I could use YDBG when it's hanging. Because what I want to do is I just want to print out like the easiest thing in the world will be to right here. Okay, that's what I want. Right there, print out every time that hits, print out EAX and EVX. Maybe if I, it did say, could use it. Okay, I want to do opt, one staging, bin, wine, DBG, help. And I want that show running process of WPID. Yeah, so I definitely want to, I want to connect to that process. Wine server, wine console. Maybe one of these, three, two, four, two, four. Three, two, four, three, six. So I don't know which one to actually three, two, four, seven, one. No. Okay, I don't actually know which one to connect to. So that's why we have to actually, okay, process and threads, blah, blah, blah. Wine debugging, wine DBG, tele.exe. Must be launched without a clear list of running processes based on the info. Info process, code map, win console, code map, win console. Nice. Okay, so I should be able to do this and I want code map. There's two code maps running. That's interesting. Let's do 35. What number do you want? All IDs are in hex. Attach to 3F. Can't attach process. It's like two. That's weird. Sorry to attach to this. Attaching. Use the attach command, pick up the WPID of the W process. It's a neat feature. I would love to use this neat feature. Can't attach process. This is insane. Sample debugging session. Wine, winward. Winward.exe. I wish this thing would just work. Where is this? It's running in a bunch of other places. 32. I gotta clean these up. 36. 426. Info process. There we go. Code map. This is something insane. If I have to do this. 102. That is literally crazy. Okay. It didn't like even the 0x to be hex before it, man. That's okay. We have adapted. We have overcome. Now we are close to hacking this guy. What I want. This right here. I desperately want that. Continue. Yes. Print slash x, eax. Oh yeah. We are cooking with gas. So ad4e is the size. And as a string ebx. Amazing. This is great. All right. So I have what I want here. Quit. Okay. Yes. We are here. All right. So we start this. See if it has commands. So that's exactly what we want. And then we can use all this debug information. So info process. So I want, oh, eight. Wow. That is super handy. Okay. So now I am attached there. And I must be getting past if there are any debug checks. I must be getting past it here. So this is why I'm attaching to it. Which means it's waiting on that read call. And so this way is nice because now I've all I'm through all the beginning stuff, which apparently was taking too long. And I don't know either we were debugging. I don't know something was going wrong there. So what I want, I want to break point on this. And okay. It's all right. Let's see. All right. So I don't couldn't have my three eight. So let's see if we can do this. So change that from 38. Nope. It's all 38 to 1056. So I want when did you be GDB. And I want 56. Oh, there we go. Okay. I'm here. Break on this address. I guess at this point I should really just turn this into a script. But let's break there. And I want my commands. Yes. Okay. So at break point one, I want to print out first print as a number star EAX. So this will print out what the size is. I want to examine as a string EBX. I think I messed that up. But let's see what happens. Undefined to create continue. No, so close. Okay. I want to set the break point on that. I want print out EAX. C O N T I N U E. Continue and point. I don't understand. Okay. That's good. Here's 998. So nine. There's all the rest though. Okay. I'm going to do this out outside of Jeff. G E F because that is not being helpful. Disable number correctly. I believe it's in like a GDP. Ah, I think it's that one. Yeah. Okay. So if I, we got this, we are going to get this answer. All right. GDP a net easy. GDP eight. Terminal crash. No. See the terminals messed up. Code map eight again. I like that. Set this. There we go. Okay. Okay. That's good. Okay. Breakpoint commands at that breakpoint print as a number EAX examine as a string, the memory that's at E B X. I'll just do C. Continue. All right. There we go. Now I got my first largest, second largest, third largest, fourth largest, fifth largest, sixth largest. So now I could do this and see what is the string inside the second largest chunk. That will be this bad boy. 10 seconds to prevent brute forcing. The third largest is going to be this guy. Nice. Wrong. Hmm. Largest is this one. The second largest is this. The third largest should be this. Hmm. So let's see. What are some things that could be wrong here? Of course, I'm trying the same example again. So that may not be actually the best idea. But largest, second largest. Let's see. Because I'm running this in wine. I'm not running this on windows. That could definitely be a problem in the sense that maybe the different. Maybe it's going to be a different breakpoint. Let's look at this. Or maybe the random number generation is different because I'm running it in wine and not on windows itself. Let's see. This would be first biggest, that second biggest, third biggest, fourth, fifth, sixth. Hmm. That's really interesting. Okay. Let's see. I think the correct thing to do at this point is going to be to set up a windows machine so I can actually run this on a windows environment. So I'm going to pause this video and set up a windows machine. All right, we're back. So here I have a windows 10 VM that is able to download through ASU's relationship with Microsoft. So here I've copied the EXE to this windows 10 instance. I can run this. It will say I'll make a thousand heap chunks of random size. Press enter to start allocating every size of the biggest chunk is 99879. The string inside that chunk is this. I'm a little bit peeve because this is the, what's going on here? Because this is exactly what we, what we had on our windows WD inside wine. So I also have the Oli debugger here. So what I want to do is I want to attach to this code map. So Oli DBG is a debugger. Attach process paused here. Why isn't it showing me any windows? I do not know. So I'm not very familiar with Oli except I've used it a very few times. Threads, windows, handles, code. What I want to do is I want to do exactly what I was doing before instead of breakpoint on this instruction of 403E67. But I need to figure out how to do this. I know I'm definitely debugging here. Maybe it's just slopes that's running in a VM. I'm not 100% certain I still have my output here. Why was this incorrect with those two? All I wait is the largest chunk, second largest, third largest, fourth largest. Okay, that doesn't seem to be helping for second third. I mean, this is definitely the string inside the third largest chunk. Okay, we want to run this. It's been a while since I've very rarely run windows anymore. So it's kind of interesting. Okay, let's see if I can open it up. Maybe I need to open up the exe and then attach to it. Nah, wrong. How is that wrong? We need to run this as admin. That definitely will help. Yes, allow that. Open code map. Oh, I think I am. Okay, so how do I breakpoints? Breakpoints? How do I tell this? I want to add a breakpoint. Here I have the different, the memory layout here. Interesting. How would I want to, like if I wanted to put a breakpoint here? Okay, I can just toggle. So I can search for stuff. Interesting. How do I, that looks terrible. Okay. Absolute addresses for sure. Go to expression. See the problem is I also can't see that. Let's see, single step, trace into, trace over. Okay, good. So at least now I'm single stepping the program. That's good. Where can I get to E67? No, that's here. It's debugging. Just entire debugging plugins. To return arguments, patches, call stacks, breakpoints, watches, references, run trace source, file, text file. Yeah, I mean the problem is I want to find, oh maybe, so if I assume maybe the O4 got changed, we're about three E67. Wonder if that would be somewhere. There's three, three E15, three E67. Yup, movie AX. Okay, so that's the breakpoint that I want. So if I right click, dump search for breakpoint. And this will run program. So is it running? See now it needs a new line from me. Is that running in, ah. Ah-ha. Here's my code map.exe that I'm debugging. Press enter. Now I'm gonna go back to Oli. Does nothing. Look at that. Okay, great. Now I am in here. So EAX AD4E. So you can see you can change this value. So AD4E. I'm gonna keep track of this. AD4E will probably be that same value that we had before. So 44355. Look here. 44366. Interesting. So good. We're already getting different results. Although this string is exactly the same. FIT. So EBX. I want though. I want this selection. Nope, no, no, no. Don't mess with that. This is what. FITZR6. TIUZOHPX. Something like that. If I continue this, so this is the first time this hits. The second time it hits now in EAX is E912122KLMIG3KB8FZP6. I'd be better way to do this, but hey. X176.0. X176.3FBI76PGCXR33D. This is like exactly the same. It's driving me crazy. All right, but what is 176.3F? Which is exactly the same thing. 184CFNJQIVNYUX7NCWLSLURKC. I guess it's possible that there is something that's looking if it's being debugged. X1855FROKVKOIZGMUKRX1862712JCU5U. Allocated merry size of the biggest chunk is that. 8, 2. So this is what I, this is exactly what I said. The third largest chunk has his agent code map. Okay, what's the string inside the second largest chunk? This doesn't work. I will definitely be a little bit upset. I don't understand. I mean, the question is, is this program detecting that it's running on windows? That's something I'm trying to think about. The biggest chunk is this 99879. Maybe there's a case where there's multiple of the same. Seems unlikely. Maybe? How do I relaunch this? Ah, why did my breakpoint went away? Let's see. How do I go and dump those on? I want to see the memory of here. 8. Oh wait, because it's such a big, it's so weird. I feel like we should have it here. I must be missing something. All right, I'm going to pause it for a bit and dig around. Okay, folks, so I'm back and I had a flash of insight. So I have not solved this yet, but I went down several false paths. But I believe I strongly now understand why they're with the problem. So what I did is I went and downloaded some plugins for AliDBG to try to get it to hide itself. I was thinking maybe this randomization function is using the is debugger present or some of these ways to detect debuggers in windows. I was a little bit skeptical because this happened both in AliDBG on the actual windows machine also on the wine environment we were using. And I was still getting the same, the same issues here. So I think we can actually go back to our original approach and the idea is I was going about this incorrectly. So we correctly know that this value is absolutely 100% the what do they call it the largest size value that it ever created. But we do not know for certain that this is the second most value. Why? Because it's constantly generating random numbers, random numbers for the size and then only keeping track of the highest number. So what we know is at some point this 18 6 27 D thrones 18 5 5 F. But what we don't know is if there's any numbers after that happens that occur between these two. So and this actually makes so much sense. And actually it was going back to the that's fine. That's fine. Going back to the Poneble dot k r level and looking at what it's actually saying. So this is a good instance where the hint is very good. The hint was look at 804 403 e 65, which was right before this jump, which outputs. So if you break point right there output e a x and e b x right there, you will see all of the sizes and strings that it generates. But what we were doing was getting here so we were getting only the largest values. So I firmly believe we can run this. So what we'll have to do then is we'll have to execute it get all 1000 of these and quickly sort them and figure out what the highest and smallest values were. So this is something I am highly confident that we can do. So we do when dbg info process. Okay, three a to do that stupid translation. There's got to be a better way to do this, but I just don't know what it is. And so we'll do do what works. If you don't know what it is do it works 58. So now we've got there now it's loading everything. I would have to hit enter. I did. We'll see. All right. Now I want to break not where I did before, but I want to break here, commands print slash d, no sign e a x, examine as a string e d e b x and continue and continue. There we go. Beautiful, beautiful, beautiful strings. So there'll be 1000 of these. I haven't quite figured out the best way it's going to be to extract all these. I mean, this is running in a screen buffer so I can actually get all of these. And once I have all of these, I mean, it should be easy, but I wonder if there's any way I can get it to like quiet mode. Okay, good. So that was it. Let's see if there's a b y o b. See if there's a way to just save this to a file. Shift F seven. I'll save this works on my weird keyboard. Control a tilde. Okay, so I can enter scroll back mode. I know how to do that here. Space to start selecting gg to the top of the buffer. Enter to copy. So now this whole windows inside the b y o b use buffer a paste. There we go. All right. And now I have everything here. So now let's open this bad guy up in my teaching own devils. Code map. I call this dump. This is great. So now I can get here. I can do dbg. So this is actually all the stuff that we want. Okay. And what am I going to do? I'm going to use Emacs. So I'm going to put a size and a string. So I'm going to write a macro. Go to dollar sign. Then go to the equal sign. And what I want is it to be in a column with the size and then the string after that. So then I need to go here. Keep doing this here. This is so awesome. And I can use the Emacs. But I'm just going to keep holding it down. I can actually see the lines. I'm at 100. It probably won't be exactly a thousand I think because it had a check where it needs to be at least 16 size. So there'll be some that are less. Actually we will do that. Yeah, I'm only 22%. So I think it's, so there we go. So now I'm going to run that. I just have Emacs do that. There we go. Until, oh no, I did do it a thousand times. 999. Dang. All right. Now we take that cat. Size and string. Let's see. Sort, sort lines of text. Well, let's just pass it to it and see what happens. Cat. Yeah, that's not working correctly. There we go. K-Pos. Key. Sort by a key. Key def gives location and type. F is a field number in both our origin one. So I think sort. I also need it as n to be numeric. Sort. There we go. And now we can see that we were definitely incorrect. So we had the correct. This is the largest. This is the second largest, but the third largest is TCK. So let's verify that that's correct. And hopefully get that sweet, sweet flag in 10 seconds. Okay. Well, I guess maybe I'm getting slightly ahead of myself, but we can actually see. Let's see. Where's this one? R-O-R-O-N-J-Q. Yeah. So there definitely is one in between those. Correct. There we go. That is going crazy. And I'm super excited. Well, this one took a long time and oftentimes that. So this is actually a good example of a case where you can see that I had to go down different code paths and, and I ended up getting stuck. I thought, oh, well, maybe the windows isn't wine actually isn't correctly emulated to the environment. So I had to install windows, try to debugging in windows, got the same result. And then that's when I realized going down that path was not the right way to go. But this is what happens sometimes. This is why, you know, when you're doing these CTF challenges, you have to make kind of a lot of different tests. And especially in this one, it took me a long time because this is something that I'm not a huge expert at reverse engineering windows binary. So that definitely took me a while. I didn't even have the environment set up. So thanks for watching and I will see you next time.