 What's going on everybody my name is John Hammond and in this video I want to showcase one of the challenges from Parsons CTF or their capture the flag a few months ago that was just classic RSA like the simple crypto system except for one small technique and trick at the very very end. So I know I've done this video at least RSA many times before but I do want to highlight and showcase really the trick at the very end because it's easy to forget. We're going to be just doing simple decryption with RSA and we're given the factors of end and the modulus which are built like to create the actual public key. So those prime numbers P and Q are actually given to us and that is what you would normally use for end in the modulus. So I've covered this again in other videos if I do a failure of some justice to actually present it to you in this video there are plenty others but I want to showcase really just the trick at the very very end. So let's go ahead and look through it. I have my terminal open here and I'll showcase the prompt. It says little Derny Johnny has a filthy mouth. He never watches his P's and Q's in fact when he encrypted a flag for us he left them lying around. Can you clean up his P's and Q's and figure out the flag? So again as I said we have these factors here and we can go ahead and calculate N and since we really have P and Q we know the factors we can determine D which is that decryption private key here. So I'll scroll down again and actually showcase some of that. Let's fire up a script and actually have the flag encrypted here and that's just a encrypted one so we'll have to read that in but let's go ahead and create a script to do all this with it. Let's say just get flag.py and I will have the Wikipedia page visible down there. Let's go ahead and have a shebang line to work with us here. Let's open up that flag.inc because that's going to be our ciphertext so I'm just going to call handle and I'll use a context manager because people yell at me handle c equals handle.read and then let's actually verify that we have the c that we want. Okay cool so that looks like nonsense. I want to go ahead and actually convert that into a number. So I'm going to use binasky because I think that's pretty well in line with the Python 3 rendition of doing these things. I will go ahead and hexalify this and then I'll consider that to be an integer. So we can go ahead and convert that as an int. If someone can tell me a better way to do that but that will go ahead and get a decimal or an integer value for me for Python to work with so let's just say c equals all of that. Great now let's go ahead and actually grab those p and q values from the original prompt. We're just going to copy and paste those in here. Okay so now we can determine n just by simply multiplying p and q and that will be handy for the rest of the evaluation but we need to really determine phi or phi or the totient. That is what's noted here in the Wikipedia article as kind of the least common multiple but with prime numbers it's actually just simple p minus 1 and q minus 1 so that's simple phi i or however you want to say that p minus 1 times the quantity of q minus 1. Now that we know phi and we can assume let's just use classic standard RSA numbers here e will go ahead and be that 65537 or in hex 0x0001. I like to remember that a little bit easier. I think it's simpler to remember than the 65535 but whatever. So now we have those values and we can go ahead and determine d. d is the modular inverse because of the way that the RSA cryptography works. We're putting together some modulus and arithmetic if we actually want to determine the private key. It is secure because of its modular components here. We can go ahead and determine that. Python offers a nice built-in way to actually calculate that with its pycryptography module. If you don't have that I think it's pseudo epip install pycrypto. I might be wrong in that. People have told me before don't use pseudo when you're trying to go ahead and pip install stuff. You either use pip install tag tag user or just work in a virtual environment. Let's go ahead and actually use that module though. It's import crypto capital C dot util capital U, capital U, number import inverse. So sorry from that package import this. So now we can go ahead and calculate d. So d will equal the inverse of e and then phi. I remember that because of e becomes before p in the alphabet. That's how I just remember those arguments. So now we should be able to determine d is a value we want it to be. It's a number. Cool. I'll trust it. Let's go ahead and calculate now. m equals the power of c raised to d all mod n. Great because that's how you go ahead and do decryption. If I scroll down here, c raised to the d all mod n is equal to m. So if I go ahead and run this, I didn't print anything out. So we're not going to sing you thing. If we were to print something out, you can see we have m here and I'm going to go ahead and convert this into a hex a decimal value. So let's do hex of that. And let's go ahead and try and convert that to ASCII. So what I'm going to do is going to first cut off that zero x. So it's at the front and go all the way to the end here, that l at the end I don't care about. So I'm going to go negative one and I have full hex a decimal value now. So let's go ahead and decode that with binasky, binasky dot unhex le phi. Then we'll pass that in. And the error that we get here is we have an odd length string. This is a stumbling block that I think a lot of people kind of didn't get when they went through this challenge. And I actually stumbled with it for way too long, too long, more longer than I should have, more longer. I don't know what I'm doing. I'm bad with words today. So what you can do here is keep in mind that if you have an odd length string that's hex, you can work with it in a similar way as you would to begin with hex already. So if I had zero x a, that's the numeric value 10, and that string of hex characters minus the zero x is just a, right? But that's an odd length string. There's only one character here. That one is not an even number. That's an odd number. If I wanted to have an even number, it would need to be a multiple of two, right? So why not? Like, what's to stop us from using zero x zero a? In hex a decimal, it's still the exact same value. It's still 10. But that string now, if I were to consider it zero a, that's an even length string. There are two values there. So if you ever see that error, odd length string, when you're trying to decode hex, that's totally fine. Just go ahead and tack on a zero either at the front or sometimes you might need it at the end. Maybe some CTF challenges will mess with you like that. I had some extra parentheses in there. Weird. Okay, I can wait. Let's try and print this out now. And I will use that technique. I do need to add the zero in here and remember that whole thing is what's being passed to hexadecimal or unhexalify. So if I print that out now, you have a lot of nonsense at the very, very top in the beginning but the flag is there NCX Dirty Jokes. So it's hidden and we would be able to carve it out. If you, for some reason, you do other processing, I tend to wrap string around that, but you shouldn't really need to all that often because hex is going to be what has the zero x and you need a slice to begin with. But that works. I think I'm thinking of it the wrong way because I'd like to use that string and then like a dot decode or something when I was using Python 2. But Python 3 is what I would advocate for now and that means using binasky dot unhexalify. So you don't need that string wrapper. Okay, that's that, right? And if you were to, if you were to actually add the zero x on at the end the, or sorry, add the new zero character on at the very, very end, that's when you would certainly need to use str to create a string and slice from that. But you would probably want to do that after you've removed the L if the L is there. So sometimes you don't really have to trust or you wouldn't want to trust that the negative one will cut an L if it's not a long value. In that case, I just use two sliced and then I just replace the L with nothing. It's a string so you can do that, right? Okay, that was a lot of talk, but really the technique and the trick that I wanted to show you is do not forget to do that if you ever see odd length string. Python will tell you that and it might be red and angry, but it's not the end of the world. So be sure to zero, just tack that on and totally fail when I forget to remove the L. Okay, I want to showcase this with Katana just to kind of, I don't know, prove that it's doing cool and good things and it's slowly coming together. I know I get anxiety and a lot of people get angry when I try and showcase Katana, but I think it's neat. So I have these two files included in the test directory that Katana is using. So let me actually get into that directory and I will go ahead and enter my virtual environment because I have been developing and I want to be in a virtual environment when I'm developing, not just doing simple CTS script code. So I'll showcase the code for this unit. It's in Katana units and it's crypto RSA. I have some baseline things for Winner's little d-attack that I don't need to show you. I'm using something called find variables now, a function that I put together to kind of track down and scan a given file for kind of the variables that would be needed in an RSA challenge. So if they ever tell you n equals this, p equals that, q equals that, d blah, blah, blah, it uses some regular expressions, pulls that out and then returns them and is able to determine them. I track down some extra cases in case it spells out the word modulus and phi or phi because it starts with a p or an m and I don't want to be confused between the words message or the factor p, right? So those are those extra odd cases. I also have a little bit of notion to go ahead and crack and then determine the n and e values from a given public key file like an open SSL certificate or that PEM key sort of thing. So that's handy and I'll showcase that in another video but that's the neat little code to do that. And parse int is what we'll go ahead and first try and determine if this is already a number, the value that we find following the string and then if it's hex, try and unhexify it or whatever, or determine it blah, blah, blah. That seems to be working pretty well actually detecting a real value and getting it returned as an integer and then we have a lot of arguments that we could potentially pass to it. I do this now to actually supply RSA c or the cipher text because that will be needed if you are passing in the target or the real first argument as the file with actual information in there. So we try and determine whether or not we could actually have a cipher text and do these things in the check or really the constructor function and then in the evaluate function or what it's actually going to try and do it goes ahead and determines whether or not we have a given e. If we don't we'll just kind of use the baseline one as I suggested earlier. We'll check if we have a Wieners little d attack because I have support for that. I also have a support for a cube root attack that I'll showcase because of a little bit of pico ctf 2018 and I determine n if it's not already given. Try and track down factors by calculating it or passing it to factor db, determine fi, I don't know why I keep saying that, determine the totian, go ahead and calculate d and then what I do is actually go ahead and do what I just showed you where I'm using that zero plus the hex value because I don't want to forget about that. So because Katana is able to process this and locate the flag in whatever data is passed to it, it finds this relatively easily and it's like pretty well. So what I'll do to run this is zshell is already auto completing it for me. Thanks. Go ahead and run Katana passing in the flag format we would expect for the ctf so ncx in this case and the dirty chani test file that has those p and q values that I need in there and then it will determine the actual c and cipher text value from reading in that flag ink. So when I run this it will go ahead and solve the challenge for me. So that was that. Super easy, super simple, and all we needed to do. The beauty of Katana and Simitar coming along too. So thank you guys for watching. I hope you enjoyed this. I know it's classic RSA and I've done it way too often but I hope that last trick and technique is a worthy foot stomp or something that I really want to drive home and not have you forget about when you play other competitions or when you see that error. Don't hesitate and just try and tinker. Add some zeros in there at the beginning or the end if you want to see if something might have been missing. So if you did like this video please do like comment and subscribe. I would love to see you guys in discord server. We have an awesome community. Link is in the description. I would be incredibly grateful to see you on patreon, paypal, and any support that you're willing to offer. I am just thankful, thankful, thankful. Can't say it enough. Thanks for watching guys. See you in the next video.