Archive for October, 2012:
Hack.LU CTF 2012: Big Zombie Business writteup
It’s a disaster! Not only that these useless piles of rotten meat obfuscate all their stupid code, they have also lost our precious root password, or “Flag” as they call it. Is there a chance you can reverse this obfuscation to extract the Flag?
credits: 200 +3 (1st), +2 (2nd), +1 (3rd)
So, we started to access the page in browsers. In chrome I couldn’t access it, so I used firefox instead for this challenge.
Now let’s see the source:
html,body{background:#000;height:100%;min−height:100%}#zombie{border:1px solid #fff;}#zombie2{color:#fff}
(\u0066\u0075\u006e\u0063\u0074\u0069\u006f\u006e(){\u0069\u0066(\u0074\u0079\u0070\u0065\u006f\u0066 \u0063\u006f\u006e\u0073\u006f\u006c\u0065==\u0075\u006e\u0064\u0065\u0066\u0069\u006e\u0065\u0064)\u0063\u006f\u006e\u0073\u006f\u006c\u0065={'\154\157\147':\u0066\u0075\u006e\u0063\u0074\u0069\u006f\u006e(){}};\u0073\u0065\u0074\u0049\u006e\u0074\u0065\u0072\u0076\u0061\u006c((\u0066\u0075\u006e\u0063\u0074\u0069\u006f\u006e(){\u0076\u0061\u0072 \u0063=\u0063\u006f\u006e\u0073\u006f\u006c\u0065.\u006c\u006f\u0067;\u0076\u0061\u0072 \u0075=\u0066\u0075\u006e\u0063\u0074\u0069\u006f\u006e(){\u0063('45\143\102\162\141\141\141\141\101\101\101\111\116\132\132\132\132','\143\157\154\157\16272\162\145\14473\146\157\156\16455\163\151\172\14572626060\160\17073')};\u0075(),\u0075(),\u0075();\u0072\u0065\u0074\u0075\u0072\u006e \u0075})(),100);\u0066=\u0066\u0075\u006e\u0063\u0074\u0069\u006f\u006e(){\u006c\u006f\u0063\u0061\u0074\u0069\u006f\u006e='\156\157\146\154\141\147'};\u006e={\u0076\u0061\u006c\u0075\u0065:\u0066,\u0063\u006f\u006e\u0066\u0069\u0067\u0075\u0072\u0061\u0062\u006c\u0065:\u0066\u0061\u006c\u0073\u0065};(\u0061=\u0064\u006f\u0063\u0075\u006d\u0065\u006e\u0074.\u0061\u0064\u0064\u0045\u0076\u0065\u006e\u0074\u004c\u0069\u0073\u0074\u0065\u006e\u0065\u0072)('\104\117\115\101\164\164\162\115\157\144\151\146\151\145\144',\u0066,\u0066\u0061\u006c\u0073\u0065);a('\104\117\115\116\157\144\145\111\156\163\145\162\164\145\144',\u0066,\u0066\u0061\u006c\u0073\u0065);\u0061('\104\117\115\103\150\141\162\141\143\164\145\162\104\141\164\141\115\157\144\151\146\151\145\144',\u0066,\u0066\u0061\u006c\u0073\u0065);\u0066\u006f\u0072(\u0069 \u0069\u006e \u006d=['\167\162\151\164\145','\167\162\151\164\145\154\156','\143\162\145\141\164\145\105\154\145\155\145\156\164','\141\160\160\145\156\144\103\150\151\154\144','\143\154\157\156\145\116\157\144\145','\151\156\163\145\162\164\102\145\146\157\162\145','\162\145\160\154\141\143\145\103\150\151\154\144','\143\162\145\141\164\145\105\154\145\155\145\156\164\116\123'])\u004f\u0062\u006a\u0065\u0063\u0074.\u0064\u0065\u0066\u0069\u006e\u0065\u0050\u0072\u006f\u0070\u0065\u0072\u0074\u0079(\u0064\u006f\u0063\u0075\u006d\u0065\u006e\u0074.\u0063\u006f\u006e\u0073\u0074\u0072\u0075\u0063\u0074\u006f\u0072.\u0070\u0072\u006f\u0074\u006f\u0074\u0079\u0070\u0065,\u006d[\u0069],\u006e);\u0076\u0061\u0072 \u0079=\u0061\u006c\u0065\u0072\u0074;\u004f\u0062\u006a\u0065\u0063\u0074.\u0064\u0065\u0066\u0069\u006e\u0065\u0050\u0072\u006f\u0070\u0065\u0072\u0074y(\u0077\u0069\u006e\u0064\u006f\u0077,'\141\154\145\162\164',{\u0076\u0061\u006c\u0075\u0065:\u0066\u0075\u006e\u0063\u0074\u0069\u006f\u006e(){\u0079('\142\162\141\141\141\151\156\172\172\172')},\u0063\u006f\u006e\u0066\u0069\u0067\u0075\u0072\u0061\u0062\u006c\u0065:\u0066\u0061\u006c\u0073\u0065});\u0076\u0061\u0072 \u007a=\u0070\u0072\u006f\u006d\u0070\u0074;\u004f\u0062\u006a\u0065\u0063\u0074.\u0064\u0065\u0066\u0069\u006e\u0065\u0050\u0072\u006f\u0070\u0065\u0072\u0074\u0079(\u0077\u0069\u006e\u0064\u006f\u0077,'\160\162\157\155\160\164',{\u0076\u0061\u006c\u0075\u0065:\u0066\u0075\u006e\u0063\u0074\u0069\u006f\u006e(\u0071){brain(z('\127\150\141\16447\16340\155\17140\172\157\155\142\151\14540\156\141\155\14577'),\u0071)},\u0063\u006f\u006e\u0066\u0069\u0067\u0075\u0072\u0061\u0062\u006c\u0065:\u0066\u0061\u006c\u0073\u0065});\u0066\u006f\u0072(\u0069 \u0069\u006e \u006d=['\143\157\156\146\151\162\155','\143\157\156\163\157\154\145'])\u004f\u0062\u006a\u0065\u0063\u0074.\u0064\u0065\u0066\u0069\u006e\u0065\u0050\u0072\u006f\u0070\u0065\u0072\u0074\u0079(\u0077\u0069\u006e\u0064\u006f\u0077,\u006d[\u0069],\u006e);})();
\u0077\u0069\u0074\u0068(\u006e\u0065\u0077 \u0058\u004d\u004c\u0048\u0074\u0074\u0070\u0052\u0065\u0071\u0075\u0065\u0073\u0074()){\u006f\u0070\u0065\u006e('\107\105\124','77\151756361',\u0066\u0061\u006c\u0073\u0065);\u0073\u0065\u006e\u0064();\u0069\u0066(\u0073\u0074\u0061\u0074\u0075\u0073==200)\u0065\u0076\u0061\u006c(\u0072\u0065\u0073\u0070\u006f\u006e\u0073\u0065\u0054\u0065\u0078\u0074)}
Hmm … some obsfucated javascript. I tried to decode some of it:
html,body{background:#000;height:100%;min−height:100%}#zombie{border:1px solid #fff;}#zombie2{color:#fff}
(function () {
if (typeof console == undefined) console = {
'log': function () {}
};
setInterval((function () {
var c = console.log;
var u = function () {
c('%cBraaaaAAAINZZZZ', 'color:red;font−size:200px;')
};
u(), u(), u();
return u
})(), 100);
f = function () {
location = 'noflag'
};
n = {
value: f,
configurable: false
};
(a = document.addEventListener)('DOMAttrModified', f, false);
a('DOMNodeInserted', f, false);
a('DOMCharacterDataModified', f, false);
for (i in m = ['write', 'writeln', 'createElement', 'appendChild', 'cloneNode', 'insertBefore', 'replaceChild', 'createElementNS']) Object.defineProperty(document.constructor.prototype, m[i], n);
var y = alert;
Object.defineProperty(window, 'alert', {
value: function () {
y('\braaainzzz')
},
configurable: false
});
var z = prompt;
Object.defineProperty(window, 'prompt', {
value: function (q) {
brain(z('What's my zombie name?'), q)
},
configurable: false
});
for (i in m = ['confirm', 'console']) Object.defineProperty(window, m[i], n);
})();
with(new XMLHttpRequest()){open('GET','?i=23',false);send();if(status===200)eval(responseText)}}
So now it’s somewhat better. Now we tried to analyse it and found that the script was sending a file named “noflag” with the content “No flag for you ” which tricked us to think that the flag was somewhere else. Also: when NoScript was activated, we saw this image in firebug console:
Now, after a lot of strugling with the javascript code, I thought to use a javascript addon to see the interpreted javascript from browser. We ran it and saw interesting things:
function brain(a, b) {
if (a === "charlie fucking sheen") {
_(b);
}
}
function _(__) {
var $ = document.querySelector("script").textContent;
var $$ = "";
for (var ___ = 0; ___ < __.length; ___++) {
$$ += String.fromCharCode(__.charCodeAt(___) ^ $.charCodeAt(___));
}
Function($$)();
alert("you are close");
}
function brain(a, b) {
if (a === "charlie fucking sheen") {
_(b);
}
}
function _(__) {
var $ = document.querySelector("script").textContent;
var $$ = "";
for (var ___ = 0; ___ < __.length; ___++) {
$$ += String.fromCharCode(__.charCodeAt(___) ^ $.charCodeAt(___));
}
Function($$)();
alert("you are close");
}
function brain(a, b) {
if (a === "charlie fucking sheen") {
_(b);
}
}
brain.toString = brain.valueOf = r = function () {location = "noflag";};
function _(__) {
var $ = document.querySelector("script").textContent;
var $$ = "";
for (var ___ = 0; ___ < __.length; ___++) {
$$ += String.fromCharCode(__.charCodeAt(___) ^ $.charCodeAt(___));
}
Function($$)();
alert("you are close");
}
_.toString = _.valueOf = r;
When inserting "charlie fucking sheen" into the box, we get some more interesting things:
And
function () {
x = document.querySelector("img")[fed];
whoop = "Flag: " + x[0] + x[377] + "_" + x[346] + x[377] + x[568] + "_" + x[18] + x[2] + x[5] + x[90] + x[90] + "_" + x[90] + x[5] + x[32] + x[9] + "_" + x[11] + x[1] + x[98] + x[1] + x[18] + x[131] + x[508] + x[5] + x[12] + x[2];
}
function anonymous() {
(function () {x = document.querySelector("img")[fed];whoop = "Flag: " + x[0] + x[377] + "_" + x[346] + x[377] + x[568] + "_" + x[18] + x[2] + x[5] + x[90] + x[90] + "_" + x[90] + x[5] + x[32] + x[9] + "_" + x[11] + x[1] + x[98] + x[1] + x[18] + x[131] + x[508] + x[5] + x[12] + x[2];}());
}
Hmm ... Exactly what we needed! Now, showing the whoop variable in firebug:
So: "do_you_still_like_javascript"
Now, I want to congrats the organisers, Team Fluxfingers, for a nice challenge and a perfect ctf, and the winners: More Smoked Leet Chicken, PPP and [TechnoPandas] Congrats!
Leetmore CTF 2012 : Stego 100 (Perfect Concealment)
We were given the cipher-text below
The giant panda (Ailuropoda melanoleuca, meaning "black and white cat-foot") is a type of bear. It lives in bamboo forests in central China. The giant panda is an endangered animal. In November 2007, China had 239 giant pandas who lived in captivity. There are 27 giant pandas which live in zoos outside of China. The exact number of giant pandas in the wild is not known. Some sources say there are about 1,590, other sources give a number between 2,000 and 3,000. The number of giant pandas in the wild seems to be increasing.
Giant pandas are about 1.2–1.5 m long and about 75 cm high. They weigh between 75 and 160 kg. Giant pandas have white fur on their bodies and black fur on their legs and shoulders. They also have black ears and black patches around their eyes. Pandas can climb and swim well.
Giant pandas are born with pink skin, with black areas on the legs, ears, and eyes. They are usually born with a small amount of white fur. They get more fur when they are about nine months old.
Giant pandas live alone. Females have a territory which they deFend against other females. When female pandas are ready to mate, they give off a special scent and make a loud bLeating noise to tell the males that they are ready. Giant pandAs mate between the months of March and May which is the Summer months in China. If there are several males, they fight each other. The one who wins – the stronGest male, then mates with the female. In August or September, the female gIves birth to one or two babies. If she has two babies, she will only raise one baby, and the other baby dies, no-one really knows how the female panda chooSe between the two. Giant panda babies are very small, and weigh only 90–130 grams, which is about 1/900 of its mother's weight. The baby drinks milk until it is 8–9 months old. Young pandas live with their mothers until they are 18–24 months old. They become mature when they are 5–7 years old. They live around 20 years in the wild and up to 30 years in captivity (e.g. in zoos). Unlike other bears, pandas do not hibernate.
Today, the giant panda is seen as a symbol for China. It is also protected by the ChineSe government, and killing a panda is a crime. ThE giant panda is now under the threat of eXtinction, and it will die out if the forests of bamboo continue to disappear.
People outside of eastern Asia did not know about the giant panda until 1869. The first "Westerner" to see a live panda was a German zoologist in 1916. In 1936, Ruth Harkness became the first Westerner to bring a live giant panda out of China. It was a cub (babY panda) named Su-Lin. The cub was taken to live at the Brookfield Zoo in Chicago.
In the 1970s, China began showing giant pandaS in zoos in the UniTed States and Japan as a type of diplomacy. This happened until 1984, when China changEd how this was done. Starting in 1984, China would allow zoos to keep the giant pandas for 10 years, but the zoo would have to pay China up to $1,000,000 each year. Also, the zoo would have to aGree that any cubs born would belong to China.
Although their bodies are made to eat meat, giant pandas are mostly herbivOrous. Their main source of food is bamboo. Because pandas have the digestive system of carnivores and can not digest cellulose very well, they get little energy and protein from the bamboo they eat. Because they get very little nutrition from bamboo, they must eat a lot. Pandas commonly eat 20 to 30 pounds of bamboo a day to get the nutrition they need. Although there are more than 200 different varieties of bamboo the Panda will only eat 20 varieties. Pandas sometimes run out of food, as a tyPe of bamboo flowers, die, and regrow again at the same time.
As of 2008, the giant bear is an endangered animal. The main problem they have is habitat loss. Habitat loss is when the places they live in are ruined. Humans often ruin the places where pandas live, such as for the construction of buildings. Pandas cAn also lose their habitat because of pollution. Pollution means that less bamboo grows, or that bamboo stops growing completely in a certain place. Giant pandas also have a low birth rate, which makes the problem worse.
TraditioNal Chinese stories about the giant pandas say that the animal can be very powerful. Some people believe that sleeping on a panda skin can protect them from ghost and predict their future. These tales are one of the reasons why people would spend lots of money for the skin and fur of this precious animal.
In former times, the panDas were also hunted. The Western people who came to China were soon unable to hunt the pandas, because of different wars. Local people continued though. PandAs were mainly hunted for their fur. Today, hunting pandas is not allowed.
In 1963, China set up a nature reserve for pandas, the Wolong National Nature Reserve. This was the firSt, other nature reserves followed. China did this to fight the number of pandas going down. In 2006, there were 40 panda reserves, compared to 13, two decades ago.
Closely looking into it reveals that some of the intermediate letters of a few words were capitalized. In one of the words, ‘O’ (English letter) was replaced by ’0′ (Numeric zero) We took out those words and listed down.
deFend
bLeating
pandAs
stronGest
gIves
chooSe
ChineSe
ThE
eXtinction
babY
pandaS
UniTed
changEd
aGree
herbivOrous
tyPe
cAn
TraditioNal
panDas
PandAs
firSt
- FLAGISEXYSTEG0PANDAS
- FLAG IS EXYSTEG0PANDAS
- FLAGISEXYSTEGOPANDAS
- EXYSTEG0PANDAS
- EXYSTEGOPANDAS………..and finally
- SEXYSTEGOPANDAS
Solution: SEXYSTEGOPANDAS
Leetmore CTF 2012 : Reverse 100 (Open Source)
We were given the following C source code:
#include
#include
int main(int argc, char *argv[]) {
if (argc != 4) {
printf("what?\n");
exit(1);
}
unsigned int first = atoi(argv[1]);
if (first != 0xcafe) {
printf("you are wrong, sorry.\n");
exit(2);
}
unsigned int second = atoi(argv[2]);
if (second % 5 == 3 || second % 17 != 8) {
printf("ha, you won't get it!\n");
exit(3);
}
if (strcmp("h4cky0u", argv[3])) {
printf("so close, dude!\n");
exit(4);
}
printf("Brr wrrr grr\n");
unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;
printf("Get your key: ");
printf("%x\n", hash);
return 0;
}`
So lets compile it:
$ gcc -o rev100 code.c
code.c: In function ‘main’:
code.c:7:6: warning: incompatible implicit declaration of built-in
function ‘exit’ [enabled by default]
code.c:13:6: warning: incompatible implicit declaration of built-in
function ‘exit’ [enabled by default]
code.c:19:6: warning: incompatible implicit declaration of built-in
function ‘exit’ [enabled by default]
code.c:24:6: warning: incompatible implicit declaration of built-in
function ‘exit’ [enabled by default]
Below is the commented source code:
#include
#include
int main(int argc, char *argv[]) {
// We need to have 4 arguments passed to the program.
// In C, the program name is a parameter too (so 3 real parameters are needed).
if (argc != 4) {
printf("what?\n");
exit(1);
}
// Convert argument 1 from a string to an integer.
unsigned int first = atoi(argv[1]);
// This integer must match the value of 0xcafe (= 51966 in decimal),
// to fail the next check.
if (first != 0xcafe) {
printf("you are wrong, sorry.\n");
exit(2);
}
// Convert argument 1 from a string to an integer.
unsigned int second = atoi(argv[2]);
// The following check fails when the integer:
// - doesn't have a modulus of 3 when dividing by 5
// and when it:
// - has a modulus of 8 when dividing by 17
if (second % 5 == 3 || second % 17 != 8) {
printf("ha, you won't get it!\n");
exit(3);
}
// This check fails if the third argument is h4cky0u.
// strcmp returns 0 (false), when there is an exact match.
if (strcmp("h4cky0u", argv[3])) {
printf("so close, dude!\n");
exit(4);
}
printf("Brr wrrr grr\n");
// Calculate the key based on the input.
unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;
printf("Get your key: ");
printf("%x\n", hash);
return 0;
}
We can use bash to convert hex values automatically and to do some
basic calculations with the $(()) construct.
(Programmers are lazy, right?)
$ ./rev100 $((0xcafe)) $((17*1+8)) h4cky0u
Brr wrrr grr
Get your key: c0ffee
$ ./rev100 $((0xcafe)) $((17*2+8)) h4cky0u
Brr wrrr grr
Get your key: c0ffee
$ ./rev100 $((0xcafe)) $((17*3+8)) h4cky0u
Brr wrrr grr
Get your key: c0ffee
Solution: c0ffee
Leetmore CTF 2012: Stego 300 (Go Through The Tunnel)
The challenge was to extract the key hidden inside the PNG image below.
By using the stego plugin for Paint.NET and extracting the 1-bit hidden image (shown below), we noticed that there seems to be a repeatable pattern in the least significant bit of a pixel.
So lets examine it a bit further.
>>> from PIL import Image
>>>
>>> # Open PNG image object.
>>> im = Image.open('stg300.png')
When we get the least significant bit of each color channel of a pixel, we see that this bit is the same for each color channel. As an example,
> Pixel: 0×0
> DecToBinary: 0000001[0]
> DecToBinary: 0000110[0]
> DecToBinary: 0001000[0]
> Pixel: 0×1
> DecToBinary: 0000010[1]
> DecToBinary: 0000111[1]
> DecToBinary: 0001001[1]
We discovered that the LSB of each color of the pixel has always the same value.
So, for pixel 0, only keep 0.
For pixel 1, only keep 1.
Thus after 8 pixels, we have 1 byte of hidden data consolidating all the bits collected.
>>> for pixel in im.getdata():
... print [color & 1 for color in pixel]
[0, 0, 0]
[1, 1, 1]
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]
[1, 1, 1]
[1, 1, 1]
[0, 0, 0]
[1, 1, 1]
[1, 1, 1]
[0, 0, 0]
[1, 1, 1]
[1, 1, 1]
[1, 1, 1]
[1, 1, 1]
[0, 0, 0]
When we look the number of pixels we can see that we have a multiple of 8, so by using only the least significant bit of one color channel of a pixel we can make full bytes.
>>> print "Number of pixels: " + str(len(list(im.getdata())))
Number of pixels: 229920
Extract the least significant bit of only one color channel of each pixel:
>>> # Store least significant bit of each pixel (of only one color) in lsb
>>> lsb = ""
>>>
>>> for pixel in im.getdata():
... # Add least significant bit of the current pixel.
... lsb += str(pixel[1] & 1)
...
>>> print "".join([ chr(int(lsb[i:i+8],2)) for i in range(0, len(lsb), 8) ])
Congrats
You win!
The
Flag
is
4E34B38257200616FB75CD869B8C3CF0 *** Congrats
You win!
The
Flag
is
4E34B38257200616FB75CD869B8C3CF0 *** Congrats
You win!
The
Flag
is
4E34B38257200616FB75CD869B8C3CF0 *** Congrats
You win!
The
Flag
is
4E34B38257200616FB75CD869B8C3CF0 *** Congrats
You win!
Solution: 4E34B38257200616FB75CD869B8C3CF0
Leetmore CTF 2012: Packets 100 (Epic Arc Pt. 1)
We were given a Wireshark capture file and the following instructions:
Epic Arc
----------
Mister You is willing to hire someone who can repeat his investigation.
Arc starts from here
Part 1. Find the secret link in this conversation
Part 2. What's the md5 of the file being transferred?
Part 3. Find and solve it. It's up to you
We loaded the file in Wireshark and converted it to libpcap format. Then again loaded the converted capture file in Network Miner.
Switching over to “Messages” tab lists down four messages out of those, the second one was obviously the key.
Solution: http://tinyurl.com/8pdox5a
Leetmore CTF 2012: PPC 200 (Oscaderp Forensic)
The challenge was to get the flag out of the files contained in the archive attached.
We need your help, soldier!
Your goal today is to help us obtain the access to Oscaderp Corp mainframe.
Our intelligence has managed to install a keylogger and a formgrabber on some bad person’s work laptop. You don’t need his name to do your job.
Everything worked as planned, the victim visited mainframe’s authentication page, https://authen.intranet/, and started to type in the password.
But when he had a couple characters left, the keylogger got busted and hard-killed by him.Present intelligence evidence:
[*] The password that’s being used is 1,048,576 characters long.
[*] According to our calculations, our keylogger managed to capture 1,048,568 password keystrokes.
[*] Formgrabber remained unnoticed, and in a few hours we’ve got the logs with successful mainframe authentication.
The only major problem: they use client-side MD5 to protect the password from being eavesdropped.
[*] We also managed to acquire the source code of the authentication mechanismYou can find all the necessary files in the archive.
YOUR GOAL: obtain the password to the mainframe, and post its SHA1 hash as the flag.
import md5
import sha
# Save the part of the password recorded by the keylogger in this variable.
# final length of recorded password = 1048568 characters
# complete password length = 1048576 characters
key_partial = ''
# Open keylogger file and extract the password related lines.
with open('keylogger_report_08_10_2012.txt', 'r') as fh:
for line in fh:
# Only look at lines that start with "Keys: ".
if line.startswith('Keys: '):
# Only extract lines that have more than 100 characters.
if len(line) > 100:
# Only extract the part after "Keys: " and don't copy
# "\r\n" and append to the partial key.
key_partial = key_partial + line[6:-2]
def bruteforce(key_partial):
"""
Bruteforce the password.
- Add "00000000" to "99999999" to the partial password.
- Compare the md5sum of this full password with the md5 hash
found in index.php ("287d3298b652c159e654b61121a858e0")
"""
md5_key_partial = md5.new()
md5_key_partial.update(key_partial)
for i in range(0,10):
print "Progress: " + str(i)
for j in range(0,10):
str_2 = str(i) + str(j)
for k in range(0,10):
str_3 = str_2 + str(k)
for l in range(0,10):
str_4 = str_3 + str(l)
for m in range(0,10):
str_5 = str_4 + str(m)
for n in range(0,10):
str_6 = str_5 + str(n)
for o in range(0,10):
str_7 = str_6 + str(o)
for p in range(0,10):
str_8 = str_7 + str(p)
md5_key_try = md5_key_partial.copy()
md5_key_try.update(str_8)
# If the md5 hash of our latest tested password matches,
# calculate the sha1 hash of this password and exit this function.
if md5_key_try.hexdigest() == "287d3298b652c159e654b61121a858e0":
sha_key = sha.new()
sha_key.update(key_partial + str_8)
print "\nSHA-key: " + sha_key.hexdigest() + "\n8 last characters: " + str_8 + "\n"
return
# Bruteforce the password.
bruteforce(key_partial)
The output from the above code was:
SHA-key: 947c83329e6cf2d9b747af59edf7974752afd741
8 last characters: 69880983
Solution: 947c83329e6cf2d9b747af59edf7974752afd741
Leetmore CTF 2012: PPC 300 (Quantum Computing Captcha)
Factorizing large numbers is hard. But, prior to solving this challenge, probably nobody knew how hard it actually is! The challenge provided an image of a large integer with the word “factorize” prepended in front of it. The PNG picture changes every time you visit the page again.
We fetched the HTML of the challenge first to have a look inside.
$ curl http://misteryou.ru/ppc300/
ReFactor