We disassemble KCaptcha, reassemble ... under .NET
KCaptcha is a fairly common PHP library for generating CAPTCHA. I have been familiar with this project for quite some time, and just as long ago one thought did not leave me: “how does everything work inside, how does it work”? Yes, it happens: the brain emits something, at first glance extremely inconspicuous and unpretentious, but then for a long time it does not lose something from the head. So it was with programming, when I first saw a piece of JavaScript code, so it was with the library from Sergey Kruglov, which I decided to study.
But first things first. I will not hide, parse and understand KCaptcha I tried many times. My attempts ended in failure. This was facilitated by a minimum of free time, and a very small number of comments in the code, and problems with motivation (it rested only on interest), but mainly, of course, the absence of at least some experience behind them.
Time passed, I took up KCaptcha, then threw it again. But time after time, through small steps, an understanding of the code came. The overall picture gradually loomed. Perhaps this will seem ridiculous to someone: think, random key generation plus output to the image! I didn’t think so. Now I look at these algorithms a bit down, but the memory of trying to understand if the code would seem complicated and at times unreasonable makes it impossible to laugh at myself.
Why bother poking around in the code? Connected, and use it on your health! Fortunately, the library makes it easy to abstract from unnecessary details. I also asked this question to myself, until I had to work on one ASP.NET project. Then there was a need to protect some pages from spammers. I think there is no need to explain that the simplest and most common way to protect yourself from bots is captcha.
Previously, I did not use anything other than PHP in my work and, of course, I have never seen CAPTCHA solutions under .NET. A quick google search did nothing but ReCaptcha wrappers in C #. A deeper analysis of the hosting for opensource projects led to some results, but these were long-abandoned, unfinished crafts. They did not even remotely resemble the familiar and already partially studied KCaptcha.
For all the previous time, I gained a little experience, and now with motivation there was now a complete order. Solved! I have to port KCaptcha from PHP to .NET.
The very first part of our program. It is from her that everything else will be repelled. The algorithm is quite simple and maybe even typical for its field of application. There is an array alphabet consisting of letters used to generate the key. N elements are randomly extracted from it, where n is the key length. Everything is elementary.
However, even in such a simple place, we move on! First, we discard all similar symbols: Have you ever had to solve a captcha where there is 0 (digit) or O (letter)? Have to? Then you can easily understand why this is done. Secondly, during generation, we monitor the combination of letters / numbers: some symbols, when partially overlapped, form hard-to-read combinations. For example, the letters r and n can be given. It is easy to understand that together they can be interpreted as m.
And so, we have a string key. It is time to transfer it to the image .
Here KCaptcha is original. Instead of vector fonts that have become the de facto standard, a set of bitmap images containing alphabet characters is used. Images are marked in a special way. This is done in order to recognize areas on which significant pixels are located (in simple terms, letters).
Here, a strip of one pixel wide at the top of the image is the markup, black pixels are significant areas, white are spaces between characters.
In fact, bitmap fonts have some advantages: we can more accurately position the result, providing better gluing of letters between each other. In addition, the raster should give an increase in performance compared to the vector and ensure independence from the installed fonts, thereby making the library cross-platform. However, there are also disadvantages: poor scalability (strong loss of quality when resizing) and a predisposition to recognition (see below).
The whole idea is to draw up a marking scale before drawing, which will be a pointer to the start and end position of each symbol. Then, guided by this scale, transfer the entire line to the image, adjusting the coordinates along the y axis a bit randomly and simultaneously replacing the gray scale with the alpha channel.
From now on, we have a fully usable library. However, there is one but! The result can filter out only very weak bots. A targeted attack of such a captcha will give a very decent percentage of recognized images. The thing is that, if the attacker has the fonts used, hacking will turn into just pixel-by-pixel enumeration of the entire captcha and its comparison with the original font files.
But there is a solution - a distorting filter . KCaptcha uses sine distortion for this, or rather, even superimposing several sine waves on top of each other. This gives a much more resilient recovery result. The results of the action of one wave can be nullified by indirect signs, but with two or more it will be more difficult.
To smooth the filter, linear interpolation is used.
I never put into practice the result of my work because of the failed site on ASP.NET. But after completion, everything turned into a small opensource project. The internal structure, algorithms, and the code itself are quite different from the original to have their own name (which, however, I did not think about for a long time). Please do not kick much - NCaptcha .
But first things first. I will not hide, parse and understand KCaptcha I tried many times. My attempts ended in failure. This was facilitated by a minimum of free time, and a very small number of comments in the code, and problems with motivation (it rested only on interest), but mainly, of course, the absence of at least some experience behind them.
Time passed, I took up KCaptcha, then threw it again. But time after time, through small steps, an understanding of the code came. The overall picture gradually loomed. Perhaps this will seem ridiculous to someone: think, random key generation plus output to the image! I didn’t think so. Now I look at these algorithms a bit down, but the memory of trying to understand if the code would seem complicated and at times unreasonable makes it impossible to laugh at myself.
Why bother poking around in the code? Connected, and use it on your health! Fortunately, the library makes it easy to abstract from unnecessary details. I also asked this question to myself, until I had to work on one ASP.NET project. Then there was a need to protect some pages from spammers. I think there is no need to explain that the simplest and most common way to protect yourself from bots is captcha.
Previously, I did not use anything other than PHP in my work and, of course, I have never seen CAPTCHA solutions under .NET. A quick google search did nothing but ReCaptcha wrappers in C #. A deeper analysis of the hosting for opensource projects led to some results, but these were long-abandoned, unfinished crafts. They did not even remotely resemble the familiar and already partially studied KCaptcha.
For all the previous time, I gained a little experience, and now with motivation there was now a complete order. Solved! I have to port KCaptcha from PHP to .NET.
Key generation
The very first part of our program. It is from her that everything else will be repelled. The algorithm is quite simple and maybe even typical for its field of application. There is an array alphabet consisting of letters used to generate the key. N elements are randomly extracted from it, where n is the key length. Everything is elementary.
However, even in such a simple place, we move on! First, we discard all similar symbols: Have you ever had to solve a captcha where there is 0 (digit) or O (letter)? Have to? Then you can easily understand why this is done. Secondly, during generation, we monitor the combination of letters / numbers: some symbols, when partially overlapped, form hard-to-read combinations. For example, the letters r and n can be given. It is easy to understand that together they can be interpreted as m.
Drawing
And so, we have a string key. It is time to transfer it to the image .
Here KCaptcha is original. Instead of vector fonts that have become the de facto standard, a set of bitmap images containing alphabet characters is used. Images are marked in a special way. This is done in order to recognize areas on which significant pixels are located (in simple terms, letters).
Here, a strip of one pixel wide at the top of the image is the markup, black pixels are significant areas, white are spaces between characters.
In fact, bitmap fonts have some advantages: we can more accurately position the result, providing better gluing of letters between each other. In addition, the raster should give an increase in performance compared to the vector and ensure independence from the installed fonts, thereby making the library cross-platform. However, there are also disadvantages: poor scalability (strong loss of quality when resizing) and a predisposition to recognition (see below).
The whole idea is to draw up a marking scale before drawing, which will be a pointer to the start and end position of each symbol. Then, guided by this scale, transfer the entire line to the image, adjusting the coordinates along the y axis a bit randomly and simultaneously replacing the gray scale with the alpha channel.
Distortion
From now on, we have a fully usable library. However, there is one but! The result can filter out only very weak bots. A targeted attack of such a captcha will give a very decent percentage of recognized images. The thing is that, if the attacker has the fonts used, hacking will turn into just pixel-by-pixel enumeration of the entire captcha and its comparison with the original font files.
But there is a solution - a distorting filter . KCaptcha uses sine distortion for this, or rather, even superimposing several sine waves on top of each other. This gives a much more resilient recovery result. The results of the action of one wave can be nullified by indirect signs, but with two or more it will be more difficult.
To smooth the filter, linear interpolation is used.
Total
I never put into practice the result of my work because of the failed site on ASP.NET. But after completion, everything turned into a small opensource project. The internal structure, algorithms, and the code itself are quite different from the original to have their own name (which, however, I did not think about for a long time). Please do not kick much - NCaptcha .