1. Си / Говнокод #20141

    −49

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    74. 74
    75. 75
    76. 76
    77. 77
    78. 78
    79. 79
    80. 80
    81. 81
    82. 82
    83. 83
    84. 84
    85. 85
    86. 86
    87. 87
    88. 88
    89. 89
    90. 90
    91. 91
    92. 92
    93. 93
    94. 94
    95. 95
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    
    int digits(char **arr_ptr, void **func_ptr)
    {
    	char *a = *arr_ptr;
    	if (*a == '9')
    	{
    		if ( *(func_ptr-1) == NULL )
    		{
    			return 0;
    		}
    		else
    		{
    			*a = '0';
    			return ( *(int(*)(char **, void **)) *(func_ptr-1) )(arr_ptr-1,func_ptr-1);
    		}
    	}
    	(*a)++;
    	return 1;
    }
    
    int az_AZ(char **arr_ptr, void **func_ptr)
    {
    	char *a = *arr_ptr;
    	if (*a == 'z')
    	{
    		*a = 'A';
    		return 1;
    	}
    	if (*a == 'Z')
    	{
    		if ( *(func_ptr-1) == NULL )
    		{
    			return 0;
    		}
    		else
    		{
    			*a = 'a';
    			return ( *(int(*)(char **, void **)) *(func_ptr-1) )(arr_ptr-1,func_ptr-1);
    		}
    	}
    	(*a)++;
    	return 1;
    }
    
    
    int main(void)
    {
    	char a[] = "$#hui"; // $ - azAZ ; # - 1234567890
    	size_t len = strlen(a);
    
    	char **char_ptr_arr = malloc(sizeof(char *) * len);
    	char **char_ptr_arr_p = char_ptr_arr;
    
    	void **func_ptr = malloc(sizeof(void *) * (len+1));
    	func_ptr[0] = NULL;
    	void **func_ptr_p = func_ptr+1;
    
    
    	char *i = a;
    	while (*i != 0)
    	{
    		if (*i == '$')
    		{
    			*char_ptr_arr_p = i;
    			char_ptr_arr_p++;
    			*func_ptr_p = (void *)az_AZ;
    			func_ptr_p++;
    			*i = 'a';
    		}
    		else if (*i == '#')
    		{
    			*char_ptr_arr_p = i;
    			char_ptr_arr_p++;
    			*func_ptr_p = (void *)digits;
    			func_ptr_p++;
    			*i = '0';
    		}
    		i++;
    	}
    
    	printf("%s ", a);
    	while (( *(int(*)(char **, void **)) *(func_ptr_p-1) )(char_ptr_arr_p-1,func_ptr_p-1) != 0 )
    	{
    		printf("%s ", a);
    	}
    	printf("%s\n", a);
    	fflush(stdout);
    	free(char_ptr_arr);
    	free(func_ptr);
    	return 0;
    }

    Перебиралка всех кобенаций паролей по маске на сишке, где функции через стек из указателей на функции друг друга вызывают через воиды.

    http://govnokod.ru/20137#comment333406 отсюда:
    Надо конечно typedef всунуть для функции, но там жопа с рекурсивным определением функции X = (int()(char **, X **))
    По сути, надо чтобы функция в качестве аргумента принимала указатель того же типа, что и та сама функция, а такое рекурсивное определение типа в Си нельзя делать

    Запостил: j123123, 06 Июня 2016

    Комментарии (17) RSS

    • > указатель того же типа, что и та сама функция, а такое рекурсивное определение типа в Си нельзя делать

      Ой я тебя умаляю, в си все можно
      Ответить
      • В машинных кодах все можно, даже ассемблер не позволяет делать особые извраты
        Ответить
        • что это такое можно в машинных кодах, чего нельзя в ассемблере?

          разве что такие опкоды, которые транслятор тупо не знает.
          Ответить
          • В асмблере можно опкоды, которые не знает транслятор
            Ответить
            • тогда это будет не совсем асемблер, а просто "вставка кодов"
              Ответить
          • Пфф, ну например если ты делаешь свой нано-JIT. Если посмотреть на инструкции x86-64 в хексах, то например
            48c7c0010000 - это mov rax, 1
            48c7c1010000 - это mov rcx, 1
            48c7c2010000 - mov rdx, 1
                ^^

            Тут меняется этот с0 c1 c2 байтик
            вот зная особенности кодирования инструкций, можно эффективно из них в рантайме собирать код. Кроме того, есть такие инструкции, которые напрямую не написать на асме. Например mov rax, 0 может быть разной длины. Разное числн нулей
            Ответить
            • В смысле генерить в райнтайме не асмовые мнемоники, а байт коды, и как-то использовать тот факт что mov rax и mov rcx отличаются на 1? Ну, это отлично конечно, но это не значит что "ассемблер не позволяет делать особые извраты".
              Ответить
              • Да, на ассемблере ты это вменяемо не закодируешь, надо разбираться в том, как инструкции кодируются, из кусочков эти штуки делать
                Ответить
              • j123123 не смог найти удачных примеров. А ведь умели же раньше люди писа́ть! Классический пример — прыжок в середину CISC-инструкции, продемонстрированный нашей любимой компанией Борланд:
                http://govnokod.ru/13242
                Ответить
                • Это слишком неинтересный пример, который разве что в вирусне(для запутывания кода) и всяких сплоитах для ROP-ов применяется. К программированию мало отношения имеет. К тому же сам прыжок можно осуществить без всяких машинных кодов, просто сместив метку при джампе
                  Ответить
                  • Жду интересных примеров.

                    Я пока не могу найти применения трюка с байтом mod-R/M (типа замены mov rax, 1 на mov rcx, 1), кроме как для написания самомодифицирующегося кода или для сокращения кода компилятора (скорее всего, последнее будет экономией на спичках).
                    Ответить
                    • Ну я практически 100% уверен, что в коде ассемблеров (nasm, yasm, fasm этц) такие трюки используются. И в коде эмуляторов, которые эмулируют чужую архитектуру. И в коде дизассемблеров
                      Ответить
                    • Вот еще макросня из-под masm
                      http://www.masmforum.com/board/index.php?topic=1622.msg12575#msg12575
                      https://github.com/dblock/dotnetinstaller/blob/master/ThirdParty/Microsoft/Windows%20SDK%20v6.0/VC/INCLUDE/listing.inc


                      .
                          time "36h,8Dh,64h,24h,00","5 bytes, lea  esp,ss:[esp+00h]   "
                          time "8Dh,9Bh,00,00,00,00","6 bytes, lea  ebx,[ebx+00000000h]"
                          time "8Dh,0A4h,24h,00,00,00,00","7 bytes, lea  esp,[esp+00000000h]"

                      Можно в rasm2 протестировать (из http://radare.org/r/ ) через консолечку
                      $ rasm2 -a x86 -b 32 -d '8d9b00000000'
                      lea ebx, [ebx]
                      $ rasm2 -a x86 -b 32 -d '8d9b00000000''8d9b00000000'
                      lea ebx, [ebx]
                      lea ebx, [ebx]
                      $ rasm2 -a x86 -b 32 'lea ebx, [ebx]'
                      8d1b
                      $ rasm2 -a x86 -b 32 'lea ebx, [ebx+00000000h]'
                      8d1b

                      Ассемблеру нельзя сказать, чтоб он эту длинную говноинструкцию с нулями сделал
                      Ответить
                      • > чтоб он эту длинную говноинструкцию с нулями сделал
                        А зачем нахуя она тебе?

                        Ради места, в которое потом можно будет воткнуть что-то ненулевое?
                        Ответить
                        • Варианты:
                          1. Ради выравнивания следующей инструкции, чтобы НОПы почём зря не вставлять.
                          2. А вдруг у инструкций разной длины пирфоманс разный? Например, на некоторых процессорах INC EAX быстрее, чем ADD EAX, 1, а на некоторых наоборот; на некоторых LOOP @1 быстрее, чем DEC ECX; ECXZ @1, а на некоторых наоборот и т. п.
                          Ответить
    • > ( *(int(*)(char **, void **)) *(func_ptr_p-1) )(char_ptr_arr_p-1,func_ptr_p-1)
      - Кастуй указатели на функцию, блять, на, кастуй указатели.
      - Как я кастовать-то буду?!
      - Вот так вот, быстро, (*)(*)(*)(*)*! Кастуй!
      Ответить

    Добавить комментарий