Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 8 октября!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

ПРОГРАММИРОВАНИЕ НА C и С++



Программисты долго мучаются с кодом прогаммы, изучают С++, WinAPI функции, MSDN. Потом пишут банальную систему защиты или навешивают банальный протектор, а крэкеры и реверсеры справляются с такой защитой за 5 минут. В итоге, продажи программы почти нулевые. Чтобы такого не допустить, тут самому надо немного поднабрать опыта отладки, реверсинга, тот же отладчик Ollydbg изучить или дизассемблер IDA Pro. Но где искать по крохам эти знания? Нет, конечно можно годами "методом тыка" разбираться, но куда быстрее видеокурс специальный посмотреть. Вот тут он есть: ссылка. Автор курса с большим опытом и объясняет понятно, я из этого курса много узнал про то как работает компьютер, процессор, про инструменты специальные и как с ними работать. Мои коллеги программисты на работе ничего такого и не знают, теперь я им нос утру.
  Листинг 1 ( главный модуль DECODE.C )


#include "std.h"
#include "errs.h"

IMPORT TEXT *malloc(); /* Standard C library allocation */

/* IMPORT INT get_byte()
*
* - This external (machine specific) function is expected to return
* either the next byte from the GIF file, or a negative number, as
* defined in ERRS.H.
*/
IMPORT INT get_byte();

/* IMPORT INT out_line(pixels, linelen)
* UBYTE pixels[];
* INT linelen;
*
* - This function takes a full line of pixels (one byte per pixel) and
* displays them (or does whatever your program wants with them...). It
* should return zero, or negative if an error or some other event occurs
* which would require aborting the decode process... Note that the length
* passed will almost always be equal to the line length passed to the
* decoder function, with the sole exception occurring when an ending code
* occurs in an odd place in the GIF file... In any case, linelen will be
* equal to the number of pixels passed...
*/
IMPORT INT out_line();

/* IMPORT INT bad_code_count;
*
* This value is the only other global required by the using program, and
* is incremented each time an out of range code is read by the decoder.
* When this value is non-zero after a decode, your GIF file is probably
* corrupt in some way...
*/
IMPORT INT bad_code_count;

#define NULL 0L
#define MAX_CODES 4095

/* Static variables */
LOCAL WORD curr_size; /* The current code size */
LOCAL WORD clear; /* Value for a clear code */
LOCAL WORD ending; /* Value for a ending code */
LOCAL WORD newcodes; /* First available code */
LOCAL WORD top_slot; /* Highest code for current size */
LOCAL WORD slot; /* Last read code */

/* The following static variables are used
* for seperating out codes
*/
LOCAL WORD navail_bytes = 0; /* # bytes left in block */
LOCAL WORD nbits_left = 0; /* # bits left in current byte */
LOCAL UTINY b1; /* Current byte */
LOCAL UTINY byte_buff[257]; /* Current block */
LOCAL UTINY *pbytes; /* Pointer to next byte in block */

LOCAL LONG code_mask[13] = {
0,
0x0001, 0x0003,
0x0007, 0x000F,
0x001F, 0x003F,
0x007F, 0x00FF,
0x01FF, 0x03FF,
0x07FF, 0x0FFF
};


/* This function initializes the decoder for reading a new image.
*/
LOCAL WORD init_exp(size)
WORD size;
{
    curr_size = size + 1;
    top_slot = 1 << curr_size;
    clear = 1 << size;
    ending = clear + 1;
    slot = newcodes = ending + 1;
    navail_bytes = nbits_left = 0;
    return(0);
}

/* get_next_code()
* - gets the next code from the GIF file. Returns the code, or else
* a negative number in case of file errors...
*/
LOCAL WORD get_next_code()  {
    WORD i, x;
    ULONG ret;

    if (nbits_left == 0)  {
        if (navail_bytes <= 0)  {

            /* Out of bytes in current block, so read next block*/
            pbytes = byte_buff;
            if ((navail_bytes = get_byte()) < 0)   return(navail_bytes);
            else if (navail_bytes)   {
                for (i = 0; i < navail_bytes; ++i)  {
                    if ((x = get_byte()) < 0)  return(x);
                    byte_buff[i] = x;
                }
            }
        }
        b1 = *pbytes++;
        nbits_left = 8;
        --navail_bytes;
    }

    ret = b1 >> (8 - nbits_left);
    while (curr_size > nbits_left)  {
        if (navail_bytes <= 0)  {

            /* Out of bytes in current block, so read next block*/
            pbytes = byte_buff;
            if ((navail_bytes = get_byte()) < 0)   return(navail_bytes);
            else if (navail_bytes)   {
                for (i = 0; i < navail_bytes; ++i)  {
                    if ((x = get_byte()) < 0)   return(x);
                    byte_buff[i] = x;
                }
            }
        }
        b1 = *pbytes++;
        ret |= b1 << nbits_left;
        nbits_left += 8;
        --navail_bytes;
    }

    nbits_left -= curr_size;
    ret &= code_mask[curr_size];
    return((WORD)(ret));
}


/* The reason we have these seperated like this instead of using
* a structure like the original Wilhite code did, is because this
* stuff generally produces significantly faster code when compiled...
* This code is full of similar speedups... (For a good book on writing
* C for speed or for space optomisation, see Efficient C by Tom Plum,
* published by Plum-Hall Associates...)
*/
LOCAL UTINY stack[MAX_CODES + 1]; /* Stack for storing pixels */
LOCAL UTINY suffix[MAX_CODES + 1]; /* Suffix table */
LOCAL UWORD prefix[MAX_CODES + 1]; /* Prefix linked list */

/* WORD decoder(linewidth)
* WORD linewidth; * Pixels per line of image *
*
* - This function decodes an LZW image, according to the method used
* in the GIF spec. Every *linewidth* "characters" (ie. pixels) decoded
* will generate a call to out_line(), which is a user specific function
* to display a line of pixels. The function gets it's codes from
* get_next_code() which is responsible for reading blocks of data and
* seperating them into the proper size codes. Finally, get_byte() is
* the global routine to read the next byte from the GIF file.
*
* It is generally a good idea to have linewidth correspond to the actual
* width of a line (as specified in the Image header) to make your own
* code a bit simpler, but it isn't absolutely necessary.
*
* Returns: 0 if successful, else negative. (See ERRS.H)
*
*/

WORD decoder(linewidth)
WORD linewidth;
{
FAST UTINY *sp, *bufptr;
UTINY *buf;
FAST WORD code, fc, oc, bufcnt;
WORD c, size, ret;

/* Initialize for decoding a new image...
*/
if ((size = get_byte()) < 0)
return(size);
if (size < 2 || 9 < size)
return(BAD_CODE_SIZE);
init_exp(size);

/* Initialize in case they forgot to put in a clear code.
* (This shouldn't happen, but we'll try and decode it anyway...)
*/
oc = fc = 0;

/* Allocate space for the decode buffer
*/
if ((buf = (UTINY *)malloc(linewidth + 1)) == NULL)
return(OUT_OF_MEMORY);

/* Set up the stack pointer and decode buffer pointer
*/
sp = stack;
bufptr = buf;
bufcnt = linewidth;

/* This is the main loop. For each code we get we pass through the
* linked list of prefix codes, pushing the corresponding "character" for
* each code onto the stack. When the list reaches a single "character"
* we push that on the stack too, and then start unstacking each
* character for output in the correct order. Special handling is
* included for the clear code, and the whole thing ends when we get
* an ending code.
*/
while ((c = get_next_code()) != ending)
{

/* If we had a file error, return without completing the decode
*/
if (c < 0)
{
free(buf);
return(0);
}

/* If the code is a clear code, reinitialize all necessary items.
*/
if (c == clear)
{
curr_size = size + 1;
slot = newcodes;
top_slot = 1 << curr_size;

/* Continue reading codes until we get a non-clear code
* (Another unlikely, but possible case...)
*/
while ((c = get_next_code()) == clear)
;

/* If we get an ending code immediately after a clear code
* (Yet another unlikely case), then break out of the loop.
*/
if (c == ending)
break;

/* Finally, if the code is beyond the range of already set codes,
* (This one had better NOT happen... I have no idea what will
* result from this, but I doubt it will look good...) then set it
* to color zero.
*/
if (c >= slot)
c = 0;

oc = fc = c;

/* And let us not forget to put the char into the buffer... And
* if, on the off chance, we were exactly one pixel from the end
* of the line, we have to send the buffer to the out_line()
* routine...
*/
*bufptr++ = c;
if (--bufcnt == 0)
{
if ((ret = out_line(buf, linewidth)) < 0)
{
free(buf);
return(ret);
}
bufptr = buf;
bufcnt = linewidth;
}
}
else
{

/* In this case, it's not a clear code or an ending code, so
* it must be a code code... So we can now decode the code into
* a stack of character codes. (Clear as mud, right?)
*/
code = c;

/* Here we go again with one of those off chances... If, on the
* off chance, the code we got is beyond the range of those already
* set up (Another thing which had better NOT happen...) we trick
* the decoder into thinking it actually got the last code read.
* (Hmmn... I'm not sure why this works... But it does...)
*/
if (code >= slot)
{
if (code > slot)
++bad_code_count;
code = oc;
*sp++ = fc;
}

/* Here we scan back along the linked list of prefixes, pushing
* helpless characters (ie. suffixes) onto the stack as we do so.
*/
while (code >= newcodes)
{
*sp++ = suffix[code];
code = prefix[code];
}

/* Push the last character on the stack, and set up the new
* prefix and suffix, and if the required slot number is greater
* than that allowed by the current bit size, increase the bit
* size. (NOTE - If we are all full, we *don't* save the new
* suffix and prefix... I'm not certain if this is correct...
* it might be more proper to overwrite the last code...
*/
*sp++ = code;
if (slot < top_slot)
{
suffix[slot] = fc = code;
prefix[slot++] = oc;
oc = c;
}
if (slot >= top_slot)
if (curr_size < 12)
{
top_slot <<= 1;
++curr_size;
}

/* Now that we've pushed the decoded string (in reverse order)
* onto the stack, lets pop it off and put it into our decode
* buffer... And when the decode buffer is full, write another
* line...
*/
while (sp > stack)
{
*bufptr++ = *(--sp);
if (--bufcnt == 0)
{
if ((ret = out_line(buf, linewidth)) < 0)
{
free(buf);
return(ret);
}
bufptr = buf;
bufcnt = linewidth;
}
}
}
}
ret = 0;
if (bufcnt != linewidth)
ret = out_line(buf, (linewidth - bufcnt));
free(buf);
return(ret);
}

  Листинг 2 ( STD.H )

#define LOCAL static
#define IMPORT extern

#define FAST register

typedef short WORD;
typedef unsigned short UWORD;
typedef char TEXT;
typedef unsigned char UTINY;
typedef long LONG;
typedef unsigned long ULONG;
typedef int INT;

  Листинг 3 ( ERRS.H )

#define OUT_OF_MEMORY -10
#define BAD_CODE_SIZE -20
#define READ_ERROR -1
#define WRITE_ERROR -2
#define OPEN_ERROR -3
#define CREATE_ERROR -4



<< ВЕРНУТЬСЯ В ПОДРАЗДЕЛ

<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ




Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU Проект ReactOS