Blog. Just Blog

Исследование защиты программы Picture Reduce

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Темная сторона Силы | Автор: ManHunter
Скриншот программы Picture Reduce
Скриншот программы Picture Reduce

Программа Picture Reduce предназначена для пакетной обработки изображений с целью изменения их размера. Вообще-то аффтар еще сам не определился с названием программы: в окне About одно название, в заголовке главного окна - другое, так что пусть будет Picture Reduce. По функционалу тоже ничего особенного, с этим прекрасно справляется множество бесплатных программ. А вот защита мне понравилась, так что подать пациента на разделочный стол.

Качаем дистрибутив, устанавливаем, запускаем. Кнопка активации в правом верхнем углу, на ввод левых регистрационных данных программа реагирует сообщением "Invalid license code!". Поищем эту строчку в исполняемом файле. Файл ничем не упакован, найдется строчка в юникоде:

Нехорошая строка найдена
Нехорошая строка найдена

Теперь посмотрим код, где это все обрабатывается:
  1. ...
  2. .text:00413F0C                 lea     ecx, [esi+604h]
  3. .text:00413F12                 mov     byte ptr [esp+18h], 1
  4. ; Получить значение полей имени и серийного номера
  5. .text:00413F17                 call    ?GetWindowTextW
  6. .text:00413F1C                 lea     ecx, [esp+4]
  7. .text:00413F20                 push    ecx
  8. .text:00413F21                 lea     ecx, [esi+658h]
  9. .text:00413F27                 call    ?GetWindowTextW
  10. .text:00413F2C                 lea     ecx, [esp+8]
  11. ; Удалить лидирующие и хвостовые пробелы
  12. .text:00413F30                 call    ds:?Trim@
  13. .text:00413F36                 lea     ecx, [esp+4]
  14. .text:00413F3A                 call    ds:?Trim
  15. .text:00413F40                 lea     ecx, [esp+4]
  16. ; Проверить длину введенного имени, оно должно быть не менее 6 символов
  17. .text:00413F44                 call    ds:?GetLength
  18. .text:00413F4A                 cmp     eax, 6
  19. .text:00413F4D                 jl      short loc_413F92
  20. .text:00413F4F                 lea     edx, [esp+4]
  21. .text:00413F53                 push    edx
  22. .text:00413F54                 lea     eax, [esp+0Ch]
  23. .text:00413F58                 push    eax
  24. .text:00413F59                 call    sub_413D60
  25. .text:00413F5E                 push    4
  26. ; Вызвать функцию проверки серийного номера
  27. .text:00413F60                 call    sub_40AF80
  28. .text:00413F65                 add     esp, 0Ch
  29. .text:00413F68                 test    eax, eax
  30. ; Если она вернула EAX=0, то серийный номер неправильный
  31. .text:00413F6A                 jz      short loc_413F92
  32. .text:00413F6C                 push    0
  33. .text:00413F6E                 mov     ecx, offset dword_4237E4
  34. .text:00413F73                 call    ds:??B?$CSimpleStringT
  35. .text:00413F79                 push    eax
  36. ; Сообщение об успешной регистрации
  37. .text:00413F7A                 push    offset aTheLicenseCode
  38. ; "The license code is valid, thank you fo"...
  39. .text:00413F7F                 mov     ecx, esi
  40. .text:00413F81                 call    ?MessageBoxW
  41. .text:00413F86                 mov     edx, [esi]
  42. .text:00413F88                 mov     ecx, esi
  43. .text:00413F8A                 call    dword ptr [edx+154h]
  44. .text:00413F90                 jmp     short loc_413FAC
  45. .text:00413F92 ; -----------------------------------------------
  46. .text:00413F92 loc_413F92:
  47. .text:00413F92                 mov     ecx, offset dword_4237E4
  48. .text:00413F97                 push    30h
  49. .text:00413F99                 call    ds:??B?$CSimpleStringT
  50. .text:00413F9F                 push    eax
  51. .text:00413FA0                 mov     ecx, esi
  52. ; Сообщение о неудачной регистрации
  53. .text:00413FA2                 push    offset aInvalidLicense
  54. ; "Invalid license code!"
  55. .text:00413FA7                 call    ?MessageBoxW
  56. .text:00413FAC loc_413FAC:
  57. .text:00413FAC                 lea     ecx, [esp+4]
  58. .text:00413FB0                 call    ds:??1?$CStringT
  59. .text:00413FB6                 lea     ecx, [esp+8]
  60. .text:00413FBA                 call    ds:??1?$CStringT
  61. .text:00413FC0                 mov     ecx, [esp+0Ch]
  62. .text:00413FC4                 pop     esi
  63. ...
Короткий путь - пропатчить функцию проверки серийного номера по адресу 40AF80, чтобы она всегда возвращала EAX=1. На этом короткий путь заканчивается и дальше можно не читать. А мы попробуем разобрать процедуру проверки серийного номера, тут как раз зарыто самое интересное в этой программе. Первую проверку валидости мы уже выяснили - длина имени должна быть не менее 6 символов. Смотрим как проверяется серийный номер.
  1. ...
  2. .text:0040AF98                 push    esi
  3. .text:0040AF99                 push    edi
  4. ; Получить значение таймера
  5. .text:0040AF9A                 push    0               ; Time
  6. .text:0040AF9C                 call    ds:_time64
  7. .text:0040AFA2                 mov     esi, [esp+2Ch+arg_0]
  8. .text:0040AFA6                 add     esp, 4
  9. .text:0040AFA9                 test    esi, esi
  10. .text:0040AFAB                 jle     short loc_40AFB2
  11. .text:0040AFAD                 cmp     esi, 6
  12. .text:0040AFB0                 jle     short loc_40AFB7
  13. .text:0040AFB2 loc_40AFB2:
  14. .text:0040AFB2                 mov     esi, 6
  15. .text:0040AFB7 loc_40AFB7:
  16. .text:0040AFB7                 call    ds:rand
  17. ; Получить случайное число с инициализацией генератора значением таймера
  18. .text:0040AFBD                 cdq
  19. .text:0040AFBE                 idiv    esi
  20. .text:0040AFC0                 mov     ecx, offset Source ; Source
  21. .text:0040AFC5                 test    edx, edx
  22. ; Вызвать один из вариантов проверки в зависимости от случайного числа
  23. .text:0040AFC7                 jz      short loc_40AFD0
  24. ; Первый вариант проверки
  25. .text:0040AFC9                 call    sub_40A6F0
  26. .text:0040AFCE                 jmp     short loc_40AFD5
  27. .text:0040AFD0 ; -------------------------------------------------
  28. .text:0040AFD0 loc_40AFD0:
  29. ; Второй вариант проверки
  30. .text:0040AFD0                 call    sub_40A790
  31. .text:0040AFD5 loc_40AFD5:
  32. ; Если любой из вариантов вернул AL=0, то серийный номер неправильный
  33. .text:0040AFD5                 test    al, al
  34. .text:0040AFD7                 jz      loc_40B081
  35. .text:0040AFDD                 mov     ecx, offset Source ; Source
  36. ; Третья проверка - обязательная
  37. .text:0040AFE2                 call    sub_40A650
  38. ; Если проверка вернула AL=0, то серийный номер неправильный
  39. .text:0040AFE7                 test    al, al
  40. .text:0040AFE9                 jz      loc_40B081
  41. ; Установить заголовок зарегистрированной версии
  42. .text:0040AFEF                 push    offset aStrfull ; "strFull"
  43. .text:0040AFF4                 lea     ecx, [esp+2Ch+arg_0]
  44. .text:0040AFF8                 mov     edi, 1
  45. .text:0040AFFD                 call    ds:??0?$CStringT
  46. ...
  47. ; часть незначимого кода пропущена
  48. ...
  49. .text:0040B06E                 mov     eax, edi
  50. .text:0040B070                 pop     edi
  51. .text:0040B071                 pop     esi
  52. .text:0040B072                 mov     ecx, [esp+20h+var_C]
  53. .text:0040B076                 mov     large fs:0, ecx
  54. .text:0040B07D                 add     esp, 20h
  55. .text:0040B080                 retn
  56. .text:0040B081 ; -------------------------------------------------
  57. .text:0040B081 loc_40B081:
  58. ; Установить триальный заголовок
  59. .text:0040B081                 push    offset aStrtrial ; "strTrial"
  60. .text:0040B086                 lea     ecx, [esp+2Ch+var_20]
  61. .text:0040B08A                 xor     esi, esi
  62. ...
Основная фишка защиты в том, что серийный номер проверяется по частям в два приема, причем первая проверка выбирается случайным образом еще из двух вариантов. Итого мы имеем три проверки серийного номера, и, если хоть одна из них не пройдена, то серийный номер считается невалидным. Но ситуация осложняется тем, что серийный номер может быть "частично" правильным, то есть он может пройти одну из первых проверок, даже несколько раз подряд, но потом "подброшенная монетка" выберет другую проверку и программа снова станет незарегистрированной. На помощь дизассемблеру приходит отладчик. Ставим точки останова на все три отмеченные процедуры проверки и запускаем программу. Первая проверка:
  1. ; Первая проверка серийного номера
  2. .text:0040A6F0                 sub     esp, 14h
  3. .text:0040A6F3                 mov     eax, dword_4236F0
  4. .text:0040A6F8                 push    esi
  5. .text:0040A6F9                 mov     esi, ecx
  6. .text:0040A6FB                 mov     [esp+18h+var_4], eax
  7. .text:0040A6FF                 lea     eax, [esi+0Eh]
  8. ; Проверить длину серийного номера
  9. .text:0040A702                 push    eax             ; Str
  10. .text:0040A703                 call    ds:wcslen
  11. .text:0040A709                 add     esp, 4
  12. .text:0040A70C                 cmp     eax, 12h
  13. ; Если длина серийника менее 12h (десятичное 18), то он неправильный
  14. .text:0040A70F                 jl      short loc_40A763
  15. .text:0040A711                 lea     ecx, [esp+18h+Str]
  16. .text:0040A715                 push    esi             ; Source
  17. .text:0040A716                 push    ecx             ; Dest
  18. .text:0040A717                 call    ds:wcscpy
  19. .text:0040A71D                 add     esp, 8
  20. .text:0040A720                 lea     edx, [esp+18h+Str]
  21. .text:0040A724                 push    edx             ; Str
Под отладчиком видно, что в начале первой функции проверки от серийного номера отделяются первые 6 символов, а затем проверяется длина оставшейся части, она должна быть не менее 18 символов. Получается, что длина правильного серийного номера как минимум 24 символа (сумма 6+18). Хорошо, вводим серийный номер, состоящий из 24 уникальных символов и повторяем регистрацию. Смотрим дальше:
  1. .text:0040A725                 mov     ecx, esi
  2. ; Преобразовать первые 6 символов серийного номера
  3. .text:0040A727                 call    sub_40A550
  4. .text:0040A72C                 lea     eax, [esp+18h+Str]
Проверка длины успешно пройдена, далее по адресу 40A550 выполняется преобразование первых 6 символов. Вот алгоритм преобразования, обозначим его как "Преобразование №1":
  1. ; Преобразование №1
  2. .text:0040A570 loc_40A570:
  3. .text:0040A570                 xor     eax, eax
  4. ; Получить следующий символ
  5. .text:0040A572                 mov     al, [esi+ecx*2]
  6. .text:0040A575                 add     al, 53h
  7. .text:0040A577                 mov     ebx, 19h
  8. .text:0040A57C                 and     eax, 0FEh
  9. .text:0040A581                 cdq
  10. .text:0040A582                 idiv    ebx
  11. .text:0040A584                 add     edx, 41h
  12. ; Записать его обратно
  13. .text:0040A587                 mov     [esi+ecx*2], dx
  14. .text:0040A58B                 inc     ecx
  15. .text:0040A58C                 cmp     ecx, edi
  16. .text:0040A58E                 jl      short loc_40A570
На выходе получаем 6 символов.
  1. .text:0040A730                 push    eax             ; Str
  2. .text:0040A731                 mov     ecx, esi
  3. .text:0040A733                 call    sub_40A5F0
Они сразу же преобразуются следующим алгоритмом, обозначим его как "Преобразование №2":
  1. ; Преобразование №2
  2. .text:0040A610 loc_40A610:
  3. .text:0040A610                 xor     eax, eax
  4. ; Получить следующий символ
  5. .text:0040A612                 mov     ax, [esi+ecx*2]
  6. .text:0040A616                 shl     ax, 3
  7. .text:0040A61A                 mov     ebx, 0Ah
  8. .text:0040A61F                 add     eax, 0C2h
  9. .text:0040A624                 movzx   eax, ax
  10. .text:0040A627                 shr     eax, 1
  11. .text:0040A629                 cdq
  12. .text:0040A62A                 idiv    ebx
  13. .text:0040A62C                 mov     ebx, 19h
  14. .text:0040A631                 xor     edx, 3
  15. .text:0040A634                 shl     edx, 3
  16. .text:0040A637                 movzx   eax, dx
  17. .text:0040A63A                 cdq
  18. .text:0040A63B                 idiv    ebx
  19. .text:0040A63D                 add     edx, 41h
  20. ; Записать его обратно
  21. .text:0040A640                 mov     [esi+ecx*2], dx
  22. .text:0040A644                 inc     ecx
  23. .text:0040A645                 cmp     ecx, edi
  24. .text:0040A647                 jl      short loc_40A610
Символы, полученные после двух преобразований, в цикле сравниваются с последними шестью символами введенного серийного номера.
  1. ; Начало цикла проверки
  2. .text:0040A738                 xor     eax, eax
  3. .text:0040A73A                 lea     ecx, [esi+26h]
  4. .text:0040A73D                 lea     ecx, [ecx+0]
  5. .text:0040A740 loc_40A740:
  6. .text:0040A740                 mov     dx, [esp+eax*2+18h+Str]
  7. .text:0040A745                 cmp     dx, [ecx]
  8. .text:0040A748                 jnz     short loc_40A763
  9. .text:0040A74A                 inc     eax
  10. .text:0040A74B                 add     ecx, 2
  11. .text:0040A74E                 cmp     eax, 6
  12. .text:0040A751                 jl      short loc_40A740
  13. .text:0040A753                 mov     al, 1
  14. .text:0040A755                 pop     esi
  15. .text:0040A756                 mov     ecx, [esp+14h+var_4]
  16. .text:0040A75A                 call    sub_415A41
  17. .text:0040A75F                 add     esp, 14h
  18. .text:0040A762                 retn
  19. .text:0040A763 ; ------------------------------------------------------
  20. .text:0040A763 loc_40A763:
  21. .text:0040A763                 mov     ecx, [esp+18h+var_4]
  22. .text:0040A767                 xor     al, al
  23. .text:0040A769                 pop     esi
  24. .text:0040A76A                 call    sub_415A41
  25. .text:0040A76F                 add     esp, 14h
  26. .text:0040A772                 retn
Отлично. Мы знаем, что последние 6 символов серийника получаются из первых 6 символов путем применения к ним сперва функций "Преобразование №1", а затем "Преобразование №2". Смотрим вторую функцию проверки.
  1. ; Вторая проверка серийного номера
  2. .text:0040A790                 sub     esp, 18h
  3. .text:0040A793                 mov     eax, dword_4236F0
  4. .text:0040A798                 push    edi
  5. .text:0040A799                 mov     edi, ecx
  6. .text:0040A79B                 push    edi             ; Str
  7. ; Заполнить массив символами "HOTUCQFRE"
  8. .text:0040A79C                 mov     [esp+20h+var_4], eax
  9. .text:0040A7A0                 mov     [esp+20h+var_18], 48h
  10. .text:0040A7A7                 mov     [esp+20h+var_16], 4Fh
  11. .text:0040A7AE                 mov     [esp+20h+var_14], 54h
  12. .text:0040A7B5                 mov     [esp+20h+var_12], 55h
  13. .text:0040A7BC                 mov     [esp+20h+var_10], 43h
  14. .text:0040A7C3                 mov     [esp+20h+var_E], 51h
  15. .text:0040A7CA                 mov     [esp+20h+var_C], 46h
  16. .text:0040A7D1                 mov     [esp+20h+var_A], 52h
  17. .text:0040A7D8                 mov     [esp+20h+var_8], 45h
  18. .text:0040A7DF                 call    ds:wcslen
  19. .text:0040A7E5                 add     esp, 4
  20. .text:0040A7E8                 cmp     eax, 6
  21. .text:0040A7EB                 jge     short loc_40A7FD
  22. .text:0040A7ED                 xor     al, al
  23. .text:0040A7EF                 pop     edi
  24. .text:0040A7F0                 mov     ecx, [esp+18h+var_4]
  25. .text:0040A7F4                 call    sub_415A41
  26. .text:0040A7F9                 add     esp, 18h
  27. .text:0040A7FC                 retn
  28. .text:0040A7FD ; -----------------------------------------
  29. .text:0040A7FD loc_40A7FD:
  30. .text:0040A7FD                 push    esi
  31. ; В цикле проверить, чтобы любой из первых 6 символов серийного номера
  32. ; был из числа символов, которые были занесены в массив
  33. .text:0040A7FE                 xor     esi, esi
  34. .text:0040A800                 test    eax, eax
  35. .text:0040A802                 jle     short loc_40A833
  36. .text:0040A804 loc_40A804:
  37. .text:0040A804                 mov     dx, [edi+esi*2]
  38. .text:0040A808                 xor     ecx, ecx
  39. .text:0040A80A                 lea     ebx, [ebx+0]
  40. .text:0040A810 loc_40A810:
  41. .text:0040A810                 cmp     dx, [esp+ecx*2+20h+var_18]
  42. .text:0040A815                 jz      short loc_40A82E
  43. .text:0040A817                 inc     ecx
  44. .text:0040A818                 cmp     ecx, 9
  45. .text:0040A81B                 jl      short loc_40A810
  46. .text:0040A81D                 pop     esi
  47. .text:0040A81E                 xor     al, al
  48. .text:0040A820                 pop     edi
  49. .text:0040A821                 mov     ecx, [esp+18h+var_4]
  50. .text:0040A825                 call    sub_415A41
  51. .text:0040A82A                 add     esp, 18h
  52. .text:0040A82D                 retn
  53. .text:0040A82E ; -------------------------------------------
  54. .text:0040A82E loc_40A82E:
  55. .text:0040A82E                 inc     esi
  56. .text:0040A82F                 cmp     esi, eax
  57. .text:0040A831                 jl      short loc_40A804
  58. .text:0040A833 loc_40A833:
  59. .text:0040A833                 mov     ecx, [esp+20h+var_4]
  60. .text:0040A837                 pop     esi
  61. .text:0040A838                 mov     al, 1
  62. .text:0040A83A                 pop     edi
  63. .text:0040A83B                 call    sub_415A41
  64. .text:0040A840                 add     esp, 18h
  65. .text:0040A843                 retn
Под отладчиком тоже хорошо видно, что сперва заполняется массив символами "HOTUCQFRE". Затем проверяется, чтобы любой из 6 первых символов серийного номера был из этого списка. Еще одна проверка пройдена, мы знаем из каких символов может состоять начало серийника. Осталась последняя проверка:
  1. ; Третья проверка серийного номера
  2. .text:0040A650                 sub     esp, 14h
  3. .text:0040A653                 mov     eax, dword_4236F0
  4. .text:0040A658                 push    esi
  5. .text:0040A659                 mov     esi, ecx
  6. .text:0040A65B                 push    edi
  7. .text:0040A65C                 lea     edi, [esi+0Eh]
  8. .text:0040A65F                 push    edi             ; Str
  9. .text:0040A660                 mov     [esp+20h+var_4], eax
  10. .text:0040A664                 call    ds:wcslen
  11. .text:0040A66A                 add     esp, 4
  12. .text:0040A66D                 cmp     eax, 6
  13. .text:0040A670                 jl      short loc_40A6D4
  14. .text:0040A672                 lea     eax, [esp+1Ch+Str]
  15. .text:0040A676                 push    esi             ; Source
  16. .text:0040A677                 push    eax             ; Dest
  17. .text:0040A678                 call    ds:wcscpy
  18. .text:0040A67E                 add     esp, 8
  19. .text:0040A681                 lea     ecx, [esp+1Ch+Str]
  20. .text:0040A685                 push    ecx             ; Str
  21. .text:0040A686                 mov     ecx, esi
  22. ; Вызвать преобразование №3
  23. .text:0040A688                 call    sub_40A5A0
Тут преобразование выполняется в три этапа. Добавился новый алгоритм, назовем его "Преобразование №3":
  1. ; Преобразование №3
  2. .text:0040A5C0 loc_40A5C0:
  3. ; Получить следующий символ
  4. .text:0040A5C0                 movzx   eax, word ptr [esi+ecx*2]
  5. .text:0040A5C4                 xor     eax, 0Bh
  6. .text:0040A5C7                 cdq
  7. .text:0040A5C8                 mov     ebx, 13h
  8. .text:0040A5CD                 idiv    ebx
  9. .text:0040A5CF                 mov     ebx, 0Ah
  10. .text:0040A5D4                 shl     edx, 1
  11. .text:0040A5D6                 movzx   eax, dx
  12. .text:0040A5D9                 cdq
  13. .text:0040A5DA                 idiv    ebx
  14. .text:0040A5DC                 add     edx, 30h
  15. ; Записать его обратно
  16. .text:0040A5DF                 mov     [esi+ecx*2], dx
  17. .text:0040A5E3                 inc     ecx
  18. .text:0040A5E4                 cmp     ecx, edi
  19. .text:0040A5E6                 jl      short loc_40A5C0
А дальше к полученной строке применяются две уже известным нам функции преобразования:
  1. .text:0040A68D                 lea     edx, [esp+1Ch+Str]
  2. .text:0040A691                 push    edx             ; Str
  3. .text:0040A692                 mov     ecx, esi
  4. ; Вызвать преобразование №2
  5. .text:0040A694                 call    sub_40A5F0
  6. .text:0040A699                 lea     eax, [esp+1Ch+Str]
  7. .text:0040A69D                 push    eax             ; Str
  8. .text:0040A69E                 mov     ecx, esi
  9. ; Вызвать преобразование №1
  10. .text:0040A6A0                 call    sub_40A550
  11. .text:0040A6A5                 xor     eax, eax
  12. .text:0040A6A7                 mov     ecx, edi
  13. ; Сравнить вторые 6 символов серийного номера с полученной строкой
  14. .text:0040A6A9                 lea     esp, [esp+0]
  15. .text:0040A6B0 loc_40A6B0:
  16. .text:0040A6B0                 mov     dx, [esp+eax*2+1Ch+Str]
  17. .text:0040A6B5                 cmp     dx, [ecx]
  18. .text:0040A6B8                 jnz     short loc_40A6D4
  19. .text:0040A6BA                 inc     eax
  20. .text:0040A6BB                 add     ecx, 2
  21. .text:0040A6BE                 cmp     eax, 6
  22. .text:0040A6C1                 jl      short loc_40A6B0
  23. .text:0040A6C3                 pop     edi
  24. .text:0040A6C4                 mov     al, 1
  25. .text:0040A6C6                 pop     esi
  26. .text:0040A6C7                 mov     ecx, [esp+14h+var_4]
  27. .text:0040A6CB                 call    sub_415A41
  28. .text:0040A6D0                 add     esp, 14h
  29. .text:0040A6D3                 retn
  30. .text:0040A6D4 ; -----------------------------------------------
  31. .text:0040A6D4 loc_40A6D4:
  32. .text:0040A6D4                 mov     ecx, [esp+1Ch+var_4]
  33. .text:0040A6D8                 pop     edi
  34. .text:0040A6D9                 xor     al, al
  35. .text:0040A6DB                 pop     esi
  36. .text:0040A6DC                 call    sub_415A41
  37. .text:0040A6E1                 add     esp, 14h
  38. .text:0040A6E4                 retn
Тут тоже ничего сложного. Снова берутся первые 6 символов серийного номера, затем к ним применяется последовательно "Преобразование №3", "Преобразование №2", а затем "Преобразование №1". Полученная строка сраванивается со вторыми 6 символами серийного номера. Третьи 6 символов серийного номера могут быть любыми. Регистрационное имя может быть вообще произвольным, оно проверяется только на минимальную длину. Вот, к примеру, серийник, который проходит все проверки: HOTFRECECEXU111111AXQXAX.

Программа успешно зарегистрирована
Программа успешно зарегистрирована

Вводим его и получаем сообщение об успешной регистрации. Так что респект аффтару за интересный алгоритм, мне понравилось. Рабочий кейген теперь напишете самостоятельно.

Поделиться ссылкой ВКонтакте
Просмотров: 4616 | Комментариев: 12

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
contango (29.05.2011 в 20:25):
ManHunter, как всегда на высоте! Да и с твоими мыслями трудно не согласиться. Препарируй и дальше такие чудо-проги. Так держать!!!
Zhelezyaka (20.05.2011 в 09:57):
Как достали эти - "нельзя так думать", воображение рисует что-то слюнявое, которое грозит пальчиком. Есть хорошая книжка "Конфедерация Меганезия", каждый волен верить во что угодно, но за навязывание своего мнения - ВМН(к стенке).
Спасибо за статью!
ManHunter (16.05.2011 в 23:45):
Все мои наработки и так в открытом доступе, а исходники я на ftp не храню. И чужие батоны я не откусываю, мне своих хватает :) Просто я против платного софта, вот и все. И уж тем более против всяких платных говноподелок, собранных на коленке. Любой софт должен быть бесплатным, и программирование должно быть творчеством, а не ремеслом. А то сейчас каждый мудак, научившийся собирать в кучу готовые компоненты и библиотеки считает себя невъебенным "программистом" и наследником Билла Гейтса.
Мнение + (16.05.2011 в 23:06):
Я считаю, что нельзя так думать, как высказался ManHunter. Если ты считаешь, что автор программы дурак, то не используй его программу. Ищи замену. Зачем откусывать чужой батон с икрой, а потом топать ножкой и кричать "не буду платить, слишком солёно". Ты же сам добровольно в рот каку взял, чего на других свою ошибку списывать. Ломать программы не строить, думаю тебе тоже будет приятно, когда с твоего ftp "вытащат" твои наработки и ты поймёшь, как "круто" ломать чужое. Не желаешь платить - не используй чужой софт, пиши свой. А писать софт высшего качества можно через лет 5, когда опыт будет, начало у всех одно. Продавать или дарить тоже дело автора, также как и право купить/не купить.
Аффтар (14.05.2011 в 20:07):
ManHunter, согласен, надо писать софт высшего качества, который люди сами захотят купить.
А по поводу помогателей, в том-то и дело, что они помогатели, а не помощники. :(
На твоем сайте есть много полезного, в какой-то мере это можно расценить как помощь. Спасибо, что она не ограничивается триалом. :)
ManHunter (14.05.2011 в 05:44):
Аффтар, RSDN уже стало не хватать? Там помогателей выше крыши. А по поводу "ломать - не строить", так на этом сайте я делюсь знаниями и своими программами, причем делаю это совершенно бесплатно. И ничего, на батон с черной икрой хватает. В остальном же меня просто вымораживает стремление "программистов", склепавших из сторонних компонентов очередной блокнот или видеоконвертер, сразу же бежать его продавать. Бабло надо зарабатывать на работе, а программировать ради удовольствия. Есть, конечно, другой вариант: надо писать софт высшего качества, который люди сами захотят купить. Это вполне реально, но для этого придется задействовать головной мозг, думать, напрягаться, творить, и количество такого софта можно пересчитать по пальцам. Похожий вариант: распространять по схеме donationware, и пусть пользователи сами решают, во сколько оценить твой труд и пользу от твоего чудо-софта.
Аффтар (14.05.2011 в 02:02):
ManHunter, а вместо того, чтобы ломать, ты мог бы помочь построить??? Или... Ломать не строить???
DimitarSerg (13.05.2011 в 12:20):
Я тоже ее ковырял, на правке одного байта остановился :)
Здесь же все грамотно расписанно именно насчет самого алгоритма генерации !
+1
AyTkACT (13.05.2011 в 11:22):
Интересная статья! Интересный алго. Разбор на пятёрку!
ManHunter (13.05.2011 в 10:28):
Я употребляю это слово в качестве презрительного названия шароварщиков.
64-ядерный процессор (13.05.2011 в 10:12):
Я как вижу статью со словом "аффтар" в начале, так не могу не удержаться, чтоб не дочитать до конца. От подобных выражений настроение подымается сразу =))
Isaev (13.05.2011 в 04:37):
Зачёт )

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

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0056 сек.) / Память: 4.5 Mb
Наверх