Skip to content

Commit a63b582

Browse files
committed
Formatting.
1 parent 0a6621d commit a63b582

16 files changed

+558
-16
lines changed

binary-exploitation/heaps-of-knowledge-420-points.md

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,53 @@ Can you pwn this? Navigate to`/problems/heaps_of_knowledge/`on the shell server
66

77
### Solution
88

9-
```
10-
TBD
11-
```
9+
This was a 420 point binary exploitation challenge. The challenge's name, Heaps of Knowledge, hints that it's probably a heap based vulnerability. So let's have a quick look. The binary presents us with a menu where we can edit, delete, and print chapters in a book. Here's what a sample run looks like:
10+
11+
![](https://raw.githubusercontent.com/VulnHub/ctf-writeups/master/images/2017/easyctf/heaps-of-knowledge/01.png)
12+
13+
And here's a run that triggers a segmentation fault:
14+
15+
![](https://raw.githubusercontent.com/VulnHub/ctf-writeups/master/images/2017/easyctf/heaps-of-knowledge/02.png)
16+
17+
From the looks of it, editing the first chunk somehow overwrote something important in the second chunk and caused the segmentation fault. A quick look at the core dump shows that EIP was overwritten with "cccc":
18+
19+
![](https://raw.githubusercontent.com/VulnHub/ctf-writeups/master/images/2017/easyctf/heaps-of-knowledge/03.png)
20+
21+
We have control over execution, half the challenge has been sovled! So what's actually happening?
22+
23+
When we edit a chapter, a book structure is populated with the chapter number, title, and a function pointer to display the text in that chapter. The function pointer points to the `print_chapter()` function, which is called when the publish option in the menu is selected. Here's what it looks like on the heap after creating two chapters:
24+
25+
![](https://raw.githubusercontent.com/VulnHub/ctf-writeups/master/images/2017/easyctf/heaps-of-knowledge/07.png)
26+
27+
The data highlighed in red show the function pointer and text belonging to chapter 1. The data highlighted in blue show the function pointer and text belonging to chapter 2. Take note of chapter 2's function pointer located at 0x98bc880 as we will overwrite this.
28+
29+
If we choose to edit chapter 1 again, it won't create a new chunk; rather it will just ask us to enter new text:
30+
31+
![](https://raw.githubusercontent.com/VulnHub/ctf-writeups/master/images/2017/easyctf/heaps-of-knowledge/08.png)
32+
33+
Notice that it uses `gets()` to read input. `gets()` doesn't do bounds checking so we can write well past this chunk and into the next chunk, thereby overwriting the function pointer assigned to chapter 2. If we set a breakpoint at the call to `gets()` we see that it is going to copy the next text into the buffer containing the old text:
34+
35+
![](https://raw.githubusercontent.com/VulnHub/ctf-writeups/master/images/2017/easyctf/heaps-of-knowledge/09.png)
36+
37+
This happens to be 32 bytes from the location of chapter 2's function pointer. So if we overwrite this pointer with the address of a function, then when we print the contens of the book, the function of our choosing will be executed. So what function should we call?
38+
39+
A quick examination of the binary shows that a function called `give_flag()` exists and isn't called anywhere. The function as you may have guessed, will open a `flag.txt` on the server and print out the flag.
40+
41+
![](https://raw.githubusercontent.com/VulnHub/ctf-writeups/master/images/2017/easyctf/heaps-of-knowledge/04.png)
42+
43+
Let's test it. I entered 32 "c"s followed by 4 "d"s. This should overwrite chapter 2's function pointer with 0x64646464:
44+
45+
![](https://raw.githubusercontent.com/VulnHub/ctf-writeups/master/images/2017/easyctf/heaps-of-knowledge/10.png)
46+
47+
Notice that the function pointer at 0x98bc880 has been overwritten. Now if we select the publish option, it will print call the function pointers in all the chapters, including the one we've overwritten.
48+
49+
So all we need to do is replace the chapter 1's text with the address of `give_flag()` and we should get the flag. I created a `flag.txt` with a dummy flag inside and ran my exploit:
50+
51+
![](https://raw.githubusercontent.com/VulnHub/ctf-writeups/master/images/2017/easyctf/heaps-of-knowledge/05.png)
52+
53+
Oh look it worked! Running it against the EasyCTF server nets us the flag:
54+
55+
![](https://raw.githubusercontent.com/VulnHub/ctf-writeups/master/images/2017/easyctf/heaps-of-knowledge/06.png)
1256

1357
### External Writeups
1458

cryptography/Genius-230-points.md

Lines changed: 0 additions & 2 deletions
This file was deleted.

cryptography/Paillier-Service-400-points.md

Lines changed: 0 additions & 2 deletions
This file was deleted.

cryptography/RSA-4-200-points.md

Lines changed: 0 additions & 2 deletions
This file was deleted.

cryptography/genius-230-points.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Genius - 230 points
2+
3+
Your boss told you that this team has come up with the cryptographic hash of the future, but something about their operation just seems a little fishy.
4+
5+
### Solution
6+
7+
Here's the site:
8+
![Screenshot 1](https://raw.githubusercontent.com/ValarDragon/CTF-Writeups/master/2017/EasyCTF/Genius/Site-1.png)
9+
![Screenshot 2](https://raw.githubusercontent.com/ValarDragon/CTF-Writeups/master/2017/EasyCTF/Genius/Site-2.png)
10+
11+
So this tells us what we have to do, crack that hash, and make `$1000000000000000`!
12+
13+
Since they hinted at their hash being twice the strength of md5, I thought I'd just put it into [crackstation's](https://crackstation.net/) hash cracker, and see whats going on.
14+
15+
![Hash cracking](https://raw.githubusercontent.com/ValarDragon/CTF-Writeups/master/2017/EasyCTF/Genius/Crackstation.png)
16+
17+
This shows us that there are 4 byte words in these hashes!
18+
Lets take the MD5 hash of `like`, and see how it compares to these strings.
19+
20+
`md5(like) = be1ab1632e4285edc3733b142935c60b`
21+
That hash is be1ab1632e4285edc3733b142935c60b90383bad42309f7f6850d2b4250a713d0b2d7a97350465a02554d29d92bfefaf
22+
23+
So, these md5's are looking like they are concatenations of 3 md5's of 4 byte strings!
24+
25+
So I split the given hash into 32 char chunks, and than began brute forcing 4 byte strings with lowercase and UPPERCASE letters, `{_}`, and numbers.
26+
This gives us:
27+
28+
```
29+
$ python3 geniusSolver.py
30+
4cc801b880dddef59829a5ad08bd8a63 0_lo
31+
d401ed3009d05ce4ef600d364a2c953e 0oO0
32+
1292b9d4dc398866ef95869b22b3941e 3_md
33+
78635bc95eaa7662a2ddf3e3d45cf108 5_we
34+
8a7fca9234d2f19c8abfcd812971a26c OMG_
35+
90383bad42309f7f6850d2b4250a713d _LIT
36+
5cca214701dbe9f7f42da7bccf074b81 _MAK
37+
ef843bee79633652a6d6ae08e964609f _no_
38+
0b2d7a97350465a02554d29d92bfefaf eral
39+
b42dad5453b2128a32f6612b13ea5d9f have
40+
00e883ab809346226dff6887080fb68b id34
41+
8c510dcaefd5061b191ad41d8b57d0ce it_t
42+
be1ab1632e4285edc3733b142935c60b like
43+
d64ddd0de1b187cd670783f5e28d681d ly_s
44+
73d559bc117f816333174e918d0587de ng_2
45+
631f5074f94b32730d0c025f1d7aacd7 ook_
46+
4f4233d6c396e8a0e6fbf597d07b8817 rrk_
47+
8d03f3f7757bdbdaaed60729d08bb180 you_
48+
OMG_it_took_like_LITerally_s0oO00_long_2_MAK3_md5_werrk_you_have_no_id34
49+
```
50+
51+
Putting that into the website's prompt gives a popup with the flag:
52+
`easyctf{OUR_3nCRYpti0n_is_N0T_br0k3n_Ur_brok3n_6c5a390d}`
53+
54+
### External Writeups
55+
56+
* [https://github.com/ValarDragon/CTF-Writeups/blob/master/2017/EasyCTF/Genius/README.md](https://github.com/ValarDragon/CTF-Writeups/blob/master/2017/EasyCTF/Genius/README.md)
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Paillier Service - 400 points
2+
3+
My friend made some sort of encryption service using the Paillier cryptosystem. Can you get him to encrypt the string `easyctf{3ncrypt_m3!}` for me? Your flag will be a base 10 integer.
4+
5+
Access his encryption service at `paillier.tcp.easyctf.com 8570`
6+
7+
### Solution
8+
9+
This was a really easy/straightforward Paillier Cryptosystem Problem! It was a great way to learn about the Paillier Cryptosystem!
10+
11+
We are not actually 'cracking' the Paillier Cryptosystem for this challenge, we are gaining the ability to encrypt our own messages already given the ability to choose the message and random number.
12+
(n,g) is the normal public key for this cryptosystem
13+
14+
We are given a service that will take a message and a random number, and encrypt it.
15+
So if we convert `easyctf{3ncrypt\_m3!}` to an integer, we get: `goal = 578781299356711768839252397261103878073419506045`
16+
17+
Just trying that in the service gives us:
18+
![That would be too easy](https://raw.githubusercontent.com/ValarDragon/CTF-Writeups/master/2017/EasyCTF/Paillier%20Service/Screenshot.png)
19+
20+
Nope, that would be too easy! So lets dive into the Paillier cryptosystem.
21+
22+
A bit of info about the Paillier Cryptosystem: Its a Homomorphic probabilistic public key cryptography system. What that means:
23+
24+
* **Homomorphism:** decryption(encryptedMessage1*encryptedMessage2) = plaintext1 + plaintext2 (recall that plaintexts are just numbers, that are decoded in different ways)
25+
* **Probabilistic:** A message can be encrypted in many different ways using the same key, so a lookup table is impossible, but all of these decrypt to the same message.
26+
27+
Because of these properties, Paillier was considered for use in voting! Since your encryption could be posted online, so you could verify your vote was included but noone would be able to decrypt it, and since anyone can verify final tallies themselves by using homomorphic property. (They were suggesting some clever math trick with the homomorphic property)
28+
29+
We only care about encryption here.
30+
There are 2 parameters, g and n that are fixed. g is some number less than n^2
31+
To encrypt a message m, you do
32+
```
33+
c = (g^m)(r^n) mod n^2
34+
```
35+
where r is a random number less than n
36+
37+
Getting g is easy! Make `m = 1, r = 1`, and then c is g!
38+
Now that we have g, increase m by 1 and put that into the service.
39+
Lets call that c, `g2`.
40+
```
41+
g2 = (g^2)(r^1) mod n^2
42+
```
43+
From the definition of modulo:
44+
```
45+
g^2 - g2 = k*n^2
46+
```
47+
If we do that for a couple of message values, `g3,g4,g5...`, we should get enough values of things that n factors into to find n. We can also test any n that we have by just raising r by 1, and seeing if we get the expected results. Additionally we know that n must be a perfect square.
48+
49+
I was about to begin coding something to check and do all that, but I decided to to put `g^2 - g2` into factordb, to see if it was something easy.
50+
51+
It turns out it couldn't have been easier! [n^2](http://factordb.com/index.php?query=5798538653888539901597848427517969653836466115517969383372708870414714499617827919081008045594866982763105646644372338947397604803459773840293469909226652409932292738680899406600644983627115148887597252501633030431493839737373550416008171962862019762627103772150765139863891942898620438599013950682968605378779376177177674907711300613428274776825775262927905232074930124107146351812226270525769638205645994715845402250228930059068632810802972672468136930221393868938524467573682405407138393007431711067835620882211146022714703452437637457743332651319267650941254285905416029921843019550300652534365188846201833030209) is the square of a [prime](http://factordb.com/index.php?id=1100000000882961502)!
52+
53+
So now we have everything we need to encrypt! Set r to 1 for convenience, and then its just a single modpow. I just used the Homomorphic property in my code, since I think its cool, but you can compute it directly.
54+
``` python
55+
m5r1 = pow(g,5,n2)
56+
goalDiv5 = goal // 5
57+
# Now use the Homomorphic property :)
58+
flagInt = pow(m5r1,goalDiv5,n2)
59+
print(flagInt)
60+
```
61+
The flag's an integer not some string that you can hex decode, since theres of tons equally valid ways to encode this message.
62+
(Imagine all the different factorizations of the goal number you can use in the modpows, or multiply different encrypted messages with different r values)
63+
64+
And thats 400 more points for us! Code used to solve the problem is in `Paillier.py`
65+
66+
I submitted
67+
```44073117240618665780675193850837939995438219250244678211539041436428154743261238082817577099306521708734123381615432054274681465095612422847370622010652215512660940106734460138798004151939831278940754163448609294265458598883535128433424615303280599380544523443593952238464672302887846705279608801286723167548136016323776193330983364067235836166569465230366```
68+
as our flag!
69+
70+
### External Writeups
71+
72+
* [https://github.com/ValarDragon/CTF-Writeups/blob/master/2017/EasyCTF/Paillier%20Service/README.md](https://github.com/ValarDragon/CTF-Writeups/blob/master/2017/EasyCTF/Paillier%20Service/README.md)

cryptography/rsa-4-200-points.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# RSA 4 - 200 points
2+
3+
After doing so much RSA, I finally messed up.... pls help. I encrypted my secret [message](../files/rsa4.txt) but the decryption isn't working!!
4+
5+
### Solution
6+
7+
\*Unfortunately due to a flag leak this challenge was taken down.
8+
9+
This was a really cool RSA problem, that I've never seen before!
10+
We're given p,q,e and C, but e is equal to 100. e can't be this value! There is no modular inverse of e mod φ(N), since e is not coprime to φ(N).
11+
12+
`GCD(e,φ(N)) != 1`, instead it is 4. (Another way of saying the above)
13+
14+
In other words, it can't invert because there is no number x, such that
15+
`ex mod φ(N) ≡ 1`
16+
since if x is large enough, instead of looping back to the beginning of the modular ring, `ex` becomes 0.
17+
18+
But! If we divide the GCD from e, that number is invertible!
19+
This will always exist, since GCD isn't 0, and because the modular inverse always exists if the number being inverted and the modulus are coprime.
20+
21+
So in our case ```e//GCD(e,φ(N)) = 25```
22+
So now we raise c to the inverse of this!
23+
Lets use the normal notation x^-1 = modInv(x,φ(N))
24+
```
25+
c ≡ m^100 mod N
26+
c^(25^-1) ≡ m^(100*(25^-1))
27+
c^(25^-1) ≡ m^(4*25*(25^-1))
28+
```
29+
Recall that by definition,
30+
```
31+
x*x^-1 ≡ 1 mod φ(N)
32+
```
33+
And recall that we only care about the exponent of m mod φ(N), because of Fermat's Little Theorem
34+
35+
so
36+
```
37+
c^(25^-1) ≡ m^(4*25*(25^-1))
38+
c^(25^-1) ≡ m^(4*1)
39+
c^(25^-1) ≡ m^4 mod N
40+
```
41+
So if we take the 4th root of c, we will get a few of the most significant bits of m! We don't get the whole thing because we don't have the exact value of C, only it modulo N.
42+
43+
```
44+
∜c^(25^-1) ≡ m mod N
45+
```
46+
47+
And that is how we get m! Coding this:
48+
49+
``` python
50+
51+
def invalidPubExponent(self,c,p="p",q="q",e="e"):
52+
53+
if(p=="p"): p = self.p
54+
if(p=="q"): q = self.q
55+
totientN = (p-1)*(q-1)
56+
n = p*q
57+
if(e=="e"): e = self.e
58+
GCD = gcd(e,totientN)
59+
if(GCD == 1):
60+
return "[X] This method only applies for invalid Public Exponents."
61+
d = self.modinv(e//GCD,totientN)
62+
c = pow(c,d,n)
63+
import sympy
64+
plaintext = sympy.root(c,GCD)
65+
return plaintext
66+
```
67+
I have coded this in [https://github.com/ValarDragon/CTF-Crypto/blob/master/RSA/RSATool.py](https://github.com/ValarDragon/CTF-Crypto/blob/master/RSA/RSATool.py) , and this is an excerpt from that, hence the self's.
68+
Running this with our input gives:
69+
70+
``` bash
71+
$ python3 RSA4.py
72+
0x656173796374667b6d3064756c34725f66754e217d
73+
bytearray(b'easyctf{m0dul4r_fuN!}')
74+
```
75+
76+
### External Writeups
77+
78+
* [https://github.com/ValarDragon/CTF-Writeups/tree/master/2017/EasyCTF/RSA%204/README.md](https://github.com/ValarDragon/CTF-Writeups/tree/master/2017/EasyCTF/RSA%204/README.md)

files/phunky2.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import operator
2+
jkx = 0 # REDACTED
3+
pork = ((12*jkx+44)/4)-(1234/617)*jkx-sum([1, 4, 7])
4+
jkx *= pork
5+
pp = filter(lambda g: not any(g % u == 0 for u in range(2, g)), range(2, 10000))
6+
b = reduce(operator.mul, (pp[i] ** int(str(jkx)[i]) for i in range(len(str(jkx)))))
7+
print b == 5481255064617348938799289747337033618255027941395204583170165268536778283633496605920691081739635039871796880258048150565371961560663189306408846812282929731768210343875396503891290782073554315141883064352279696582873577061230377462942383580274252927462973332664209357720446443158594967136490465000

files/rsa4.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
p= 13013195056445077675245767987987229724588379930923318266833492046660374216223334270611792324721132438307229159984813414250922197169316235737830919431103659
2+
q= 12930920340230371085700418586571062330546634389230084495106445639925420450591673769061692508272948388121114376587634872733055494744188467315949429674451947
3+
4+
e= 100
5+
6+
C= 2536072596735405513004321180336671392201446145691544525658443473848104743281278364580324721238865873217702884067306856569406059869172045956521348858084998514527555980415205217073019437355422966248344183944699168548887273804385919216488597207667402462509907219285121314528666853710860436030055903562805252516

programming/Match-Me-300-points.md

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)