[stranger@localhost ~]$ date
Сбт Дек 5 00:23:09 MSK 2009

[stranger@localhost ~]$ cat /home/stranger/h3kcode.txt
Ну для начала стоит определиться что такое «хаки».
В моем понимании это какие то нестандартные, красивые, оригинальные решение, которые явно отличаются от других. В общем что то умное и не ординарное. Собственно в этой статье я приведу пример нескольких хаков на тему кодинг. Вообще зачем они нужны? По моему главная причина это так называемый brainfuke, который является любимый занятием любого хакера/кодера. Ну и вторая причина читать данный материал – повышение уровня знания языка. Кстати примеры будут на Си.
Ну что ж. Теперь, когда я заполнил выделенную память введением, можно начинать fuke.


---[h3k 01] ---
//Очень маленькое тело
Первый хак заключается в том, что бы написать программу, которая выводила 10 раз подряд рандомные (псевдослучайные) числа. Но. Тело функции main() не должно превышать 4 символов. При том – нельзя писать доп. Функции, нельзя инклудить какие либо файлы кроме stdio.h.

Думаю ясно что 4 символами такую программу не написать (а может можно?)). Нам нужно куда то вынести этот код:

int i=0;
while(i[10)
{
printf(%i,rand(1000));
}

Но не забываем, что функции создавать нельзя. Но с помощью макроподстановок в дириктиве #define можно выполнить этот код. Смотрим:

#include [stdio.h]
#define RND int i=0,g=random(100); while(i[10){printf("%d",g);printf("\n");i++;}

int main()
{
RND;
}

Ну вот.) получилась программа из трех букв xdd
На самом деле макроподстановка довольно удобная вещь. К примеру показ баннера вашей программы. Достаточно написать

#define banner printf(«Powed by StraNger»);

И не нужно пихать код в отдельную функцию

---[h3k 02] ---
//Цикл без цикла
Давайте попробуем сделать такой трюк – нужно написать программу которая бы перебирала указанные числа по порядку и каждое новое число сумировало с предыдущим.
Но главная задача в том, что бы не использовать при этом операторы циклов.

Для начала давайте прикинем какой код будет если мы внедрим цикл(для 10 раз):

- - -
int i=0, stat=5;
while(i[10)
{
stat=stat+(stat-1);
i++;
}
- - -

Теперь нужно избавится от цикла. Конечно, можно было бы выполнять 10 раз схожий код, но это как минимум глупо. Давайте лучше вспомним, что такое оператор goto. Как известно от служит для “прыжка” программы к какой либо метке. Ну например:

- - -
if(a]0)
goto error;
else
//Тут какие то действия
errot:
printf(“OH!\n”);
- - -

Если а>0 то программа перескочит к метке error и выполнит код, который мы в ней написали.
А что нам мешает таким образом организовать цикличные действия. С помощью двух меток и двух goto. Смотрим:

#include [stdio.h]
int main()
{
int i=2,stat=0;
//Первая ссылка
one:
if(stat[10)
{
i=i+(i-1);
stat++;
goto tho;
}
else
printf("The end, i=%d",i);

}
}

Когда программа доходит до первой ссылки она проверяет переменную stat. Если она еще меньше 10, то нужно выполнять вычисления (как очередной шаг цикла) и увеличивать счетчик. Далее происходит переход ко второй метке , там выполяется точно такая же проверка.
Внимательный читатель заметит, что программу можно значительно уменьшить.
Вот так:

#include [stdio.h]
int main()
{
int i=2,stat=0;

one:
if(stat[10)
{
i=i+(i-1);
stat++;
goto one;
}
else
printf("The end, i=%d",i);
}

Как видите мы попросту выполнили переход к этой же метке.
goto самый ненавистный си оператор.
Эдсгера Дейкстры сказал: “качество программного кода обратно пропорционально количеству операторов GOTO в нём"
Действительно код становится мене понятным. Но как видите иногда его можно применить весьма оригинальным способом.
На самом деле, это не единственный способ организовать “цикл без цикла”
Если вызывать функцию рекурсивной, а в ней проверять значение счетчика получится примерно тоже самое. Вот так:

int step();
int i;
int main()
{
step();
}

int step()
{
if(i[10)
{
i++;
step();
}
else
printf("%i",i);
}



---[h3k 03] ---
//Обманутый strcmp
В этом хаке мы попытаемся обмануть функцию strcmp. Как надеюсь вы знаете он сравнивает две строки, нам же нужно что бы эти строки были не равны между собой, а функция определило противное.

На самом деле тут ничего сложного. Давайте посмотрим как например строка fukeworld располагается в памяти:
f a k e w o r l d\0
нас интересует именно конечный символ \0 он указывает на окончание строки.
Теперь вспомним, как работает strcmp. Она сравнивает две строки посимвольно до символа окончания строки (\0). Вы наверное поняли к чему я веду. Если нет смотрим пример:

#include [stdio.h]
int main(int argc, char argv[])
{
int integ;
char *w1="fuke\0world";
char *w2="fake";
integ=strcmp(w1,w2);
printf("%i\n",integ);
}

Здесь мы так скажем принудительно указали конец строки, используя символ \0. Если отсечь часть после него, то получатся как раз равные строки.
Если вы протестируете пример, то программа должна вывести на дисплей цифру 0. Это результат выполнения функции strcmp, значит строки равны.

Ну а если сделать так:

char *w1="\0fuke world";
то все будут думать, что строка пуста.

---[h3k 04] ---
//forever... oh no!
Представим себе вот такой код:

#include [stdio.h]
int main(int argc, char argv[])
{
int i=1;
for(i=1;i]0;i++)
{
printf("forever");
}
}

Как видите здесь запускается бесконечный цикл. В нем на экран выводится слово forever.
Хак заключается в том, что бы изменить программу таким образом, что наш цикл через какое то время останавливался и не был бесконечным. При том нельзя писать какие то операторы перед циклом (и в нем соответственно), нельзя создавать функции.

Здесь нам на помощь приходит опять #define. Нужно задать какую то константу, которая бы изменила работу цикла. В теле используется только printf, значит ее и нужно подставить в define:


#include [stdio.h]
#define printf continue;
int main(int argc, char argv[])
{
int i=1;
for(i=1;i]0;i++)
{
printf("forever");
}
}

Попробуйте запустить и вы уведите, что цикл не бесконечный. Точнее он не будет выполняться вообще.

---[h3k 05] ---
//10 способов создать бесконечный цикл.
С первого взгляда кажется способов выполнения действия бесконечное число раз не так уж и много. Но на самом деле это не так. Посидев 5 минут с блокнотом я нашел 10 способов (откинув однотипные решения), хотя думаю что можно найти их гораздо больше


***************
1) while(true) {}
***************


**************
2)for (;;) {}
**************


**************
3)
int i;
for (i=0;i]0;i++) {}
**************


**************
4)
int i=1;
while(i]0)
{i++}
**************


**************
5)
repeat:
printf("h");
goto repeat;
**************


**************
6)
int i;
repeat:
i=0;
while(i[1)
{
goto repeat;
i++;}
*************


*************
7)
while(1==1)
{}
*************


*************
8)
while("")
{}
*************


*************
9)
int i;
rock:
do
{
goto rock;
i++;
}
while(i[10); //самое интересное, что тут условие вообще будет игнорироваться
************


************
10)
int i;

for(i=0;i[10;i++)
{
if(i[10)
i--;
}
************
---[h3k 06] ---

//без условия.
Хак заключается в следующем – нужно написать программа которая бы принимало какое то число аргументов. В каждом аргументе находится один символ, программе нужно найти среди них нужный (пусть будет 'w'). При том – нельзя пользоваться условными конструкциями (кроме условия И ИЛИ).

Для сравнения строк будет использовать функцию strcmp(). При полном совпадении она возвращает ноль. Проблема как раз в том, как проверить результат функции.
Смотрим код:


#include [stdio.h]

int main(int argc, char *argv[])
{
int i;
for(i=0;i[argc;i++)
{
(strcmp(argv[i],"w")!=0) || printf("Нужная буква в(во) %i аргументе\n",i+1);
}
}

Происходит примерно так:
значение функции strcmp не равно нулю или (равно нулю) мы нашли нужный символ. Как видите несложно.
Первый хак заключается в том, что бы написать программу, которая выводила 10 раз подряд рандомные (псевдослучайные) числа. Но. Тело функции main() не должно превышать 4 символов. При том – нельзя писать доп. Функции, нельзя инклудить какие либо файлы кроме stdio.h.

EOF
StraNger