Сборный / Говнокод #25370 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  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
format pe console 5.0

entry start

include 'win32ax.inc'

SLEEP=1000

section '.data' data readable

  _hello db 'Hello "https://www.govnokod.ru/"!',13,10,0
  _conout db 'CONOUT$',0
  align 8
  _conoutnt du '\??\CONOUT$',0

section '.data?' data readable writeable

  bytes_write dd ?
  houtput dd ?
  length dd ?

section '.text' code readable executable

start:
  call _novice
  invoke Sleep,SLEEP
  call _advanced
  invoke Sleep,SLEEP
  call _psycho
  invoke Sleep,SLEEP
  invoke ExitProcess,0

_novice:
  invoke GetStdHandle,STD_OUTPUT_HANDLE
  mov [houtput],eax
  invoke lstrlen,_hello
  mov [length],eax
  invoke WriteConsole,[houtput],_hello,[length],bytes_write,0
  ret

_advanced:
  invoke CreateFileA,_conout,GENERIC_WRITE,0,0,OPEN_EXISTING,0,0
  mov [houtput],eax
  invoke lstrlen,_hello
  mov [length],eax
  invoke WriteFile,[houtput],_hello,[length],bytes_write,0
  invoke CloseHandle,[houtput]
  ret

_psycho:
  push ebx
  sub esp,40
  mov ebx,esp
  mov word[ebx+24],22
  mov word[ebx+26],24
  mov dword[ebx+28],_conoutnt
  mov dword[ebx+0],24
  mov dword[ebx+4],0
  lea eax,[ebx+24]
  mov dword[ebx+8],eax
  mov dword[ebx+12],$00000040
  mov dword[ebx+16],0
  mov dword[ebx+20],0
  lea eax,[ebx+32]
  invoke NtCreateFile,houtput,$40100080,ebx,eax,0,0,0,1,$60,0,0
  invoke lstrlen,_hello
  mov [length],eax
  lea eax,[ebx+32]
  invoke NtWriteFile,[houtput],0,0,0,eax,_hello,[length],0,0
  invoke NtClose,[houtput]
  add esp,40
  pop ebx
  ret

section '.import' data import readable

  library\
    ntdll,'ntdll.dll',\
    kernel32,'kernel32.dll'

  import ntdll,\
    NtClose,'NtClose',\
    NtCreateFile,'NtCreateFile',\
    NtWriteFile,'NtWriteFile'

  include 'api\kernel32.inc'

section '.reloc' fixups data readable discardable

Интересно какой из методов (_novice, _advanced, _psycho) вывода в консоль является говнокодом?

Запостил: chiacorp chiacorp, (Updated )

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

  • Помоему здесь самый нормальный это _novice. Только я бы здесь не звал lstrlen каждый раз, а написал бы
    mov [length], _conout - _hello - 1


    Мне вот, кстати, непонятно, почему Томаш, написав ассемблер с таким классным препроцессором, сам не юзает макросы в исходниках fasm, и даже таблицы импорта руками собирает?
    Ответить
    • Может быть так бутстрапнуться проще было? Самая первая версия же явно не сама собой конпелялась? А потом так и оставил.
      Ответить
      • Первые версии на tasm'е были, но синтаксис у fasm с tasm'ом не совсем совместим, значит чавой-то там ему всё равно приходилось переписывать. Да и потом много чего ещё дописано было.

        Ассемблерщики любят ручками поработать, любят сэкономить лишний байт, лишний проход и лишнюю милисекунду конпеляции. Именно поэтому я за "assembler".
        Ответить
        • Писать конпелятор на асме - немного странная идея, имхо. Проблем со скоростью конпеляции не было бы даже на каком-нибудь питоне.
          Ответить
          • Вообще проблем со скоростью конпеляции программ на ассемблере нет.

            Надо бы придумать fasm++, с классами, шаблонами, констэкспрами и прочей хуйнёй и наметушить огромную библиотеку, чтобы программы конпелировались по джва часа.
            Ответить
    • Кстати, а где задаётся соглашение для invoke? Или там тупо всегда stdcall?
      Ответить
        • А fastcall и 64-битные соглашения где первые аргументы в регистрах тоже умеет?
          Ответить
            • А как обращаются с регистрами, которые будет юзать invoke? Или он сам их бекапит если надо?

              З.Ы. Я просто никогда invoke в асмах не юзал, всегда push/mov вручную писал подглядывая в соглашение о вызовах.
              Ответить
                • Определение размера параметра по опкоду инструкции (наверное не говно, но код интересный):
                  else if ~ param in <xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15>
                  	virtual
                  	 origin = $
                  	 inc param
                  	 load opcode byte from origin
                  	 if opcode = 67h | opcode = 41h
                  	  load opcode byte from origin+1
                  	 end if
                  	 if opcode and 0F8h = 48h
                  	  size@param = 8
                  	 else if opcode = 66h
                  	  size@param = 2
                  	 else if opcode = 0FFh
                  	  size@param = 4
                  	 else
                  	  size@param = 1
                  	 end if
                  	end virtual
                         end if
                  Ответить
              • А можно ссыль на эти соглашения?
                Ответить
                • На вики вроде неплохо расписаны.

                  З.Ы. На английской. На русской только 32-битные перевели.
                  Ответить
  • > https
    Блин, я сначала подумал, что это парсер ГК на асме...

    > _psycho
    А напрямую через syscall, как недавно для линукса делали, тогда кто? 🙂
    Ответить
      • ;Windows 10 Pro x64
        _shizo:
        push ebx edi
        xor edi,edi
        sub esp,40
        mov ebx,esp
        mov word[ebx+24],22
        mov word[ebx+26],24
        mov dword[ebx+28],_conoutnt
        mov dword[ebx+0],24
        mov dword[ebx+4],edi
        lea eax,[ebx+24]
        mov dword[ebx+8],eax
        mov dword[ebx+12],$00000040
        mov dword[ebx+16],edi
        mov dword[ebx+20],edi
        lea eax,[ebx+32]
        push edi
        push edi
        push $60
        push 1
        push edi
        push edi
        push edi
        push eax
        push ebx
        push $40100080
        push houtput
        push edi
        mov eax,$55
        mov edx,$775BEA50
        call edx
        add esp,$30;$2C
        invoke lstrlen,_hello
        mov [length],eax
        lea eax,[ebx+32]
        push edi
        push edi
        push [length]
        push _hello
        push eax
        push edi
        push edi
        push edi
        push [houtput]
        push edi
        mov eax,$1A0008
        mov edx,$775BEA50
        call edx
        add esp,$28
        push [houtput]
        push edi
        mov eax,$3000F
        mov edx,$775BEA50
        call edx
        add esp,$8
        add esp,40
        pop edi ebx
        ret
        Ответить
          • Ну sysenter прямо из своего кода он не сможет дёрнуть по понятным причинам. Так что тут или этот переходник звать, или прерывание (если в винде оно ещё живое) или забить хуй на x86 и под amd64 дёргать syscall...

            З.Ы. Или можно call + systenter? Я просто не помню, что делает переходник после возврата из сисколла. Если там просто ret - то прокатит.
            Ответить
                • Верно, зато работать оно должно на любой винде, вне зависимости от того, по какому адресу размещены функции из ntdll. На моей Win10 x64, к примеру, NtCreateFile сидит на 0x00007FFAFA030910.
                  Ответить
                  • Дык похуй по какому адресу висит ntdll. Вообще никакие адреса знать не надо. Декомпилируешь ntdll, смотришь номера сисколлов и регистры. Остаётся заполнить их и дёрнуть инструкцию syscall (для amd64).

                    З.Ы. Но я х.з. насчёт стабильности виндовых сисколлов. Надо исследовать разные версии венды. Так то твой способ надёжнее.
                    Ответить
                    • Сисколлы действительно нестабильны. Более того, в разных версиях виндов они вообще по-разному реализованы. В моей винде, к примеру:
                      mov r10,rcx
                      mov eax,0x55
                      test byte ptr ds:[0x7FFE0308],0x1
                      jne ntdll.7FFAFA030925
                      syscall
                      ret
                      int 0x2E
                      ret

                      Флаг на 0x7FFE0308 — какое-то поле в KUSER_SHARED_DATA, видимо, поддерживает ли процессор «syscall».

                      А вот добрые люди ведут список сисколлов: https://j00ru.vexillium.org/syscalls/nt/64/
                      Ответить
                    • > Декомпилируешь ntdll

                      Декомпилировал ntdll от «Windows 95». Оказывается, на не-NT сделали шиворот-навыворот: ntdll импортирует функции из kernel32. Это примерно как на заборе слово «МЕЛ» написать...
                      Ответить
                • А вообще, это полотнище — кусок моей старой попытки создания универсального шеллкода-загрузчика, который бы мог грузить заданную дллку в процессах любой битности, при необходимости переключаясь в x32/x64 и обратно.
                  Ответить
            • >сли в винде оно ещё живое)
              конечно, иначе какбы работали старые программы до сисенторовй эпохи?

              ABI то сохранять надро
              Ответить
              • Кстати, на «AMD» инструкции «SYSENTER/SYSEXIT» не работают в длинном режиме. На них в длинном нужно использовать «SYSCALL/SYSRET». Как достигается совместимость? Под «AMD» пишут отдельный HAL?
                Ответить
  • Раздутый говношеллкод: может стартовать из любого адреса; по окончанию полностью восстанавливает состояние регистров.
    format PE64 console
    
    use64;
    jmp start
    kernel32_namew du "kernel32.dll",0
    kernel32_handle dq 0
    
    write_console_name db "WriteConsoleA",0
    write_console_address dq 0
    
    get_std_handle_name db "GetStdHandle",0
    get_std_handle_address dq 0
    
    hello_world db "Hello World!"
    hello_world_len = $ - hello_world
    
    hole dq 0
    
    start:
    push rbp
    push rax
    push rcx
    push rdx
    push r8
    push r9
    push r11
    
    mov rbp, rsp
    sub rsp, 0x30
    and rsp, 0xFFFFFFFFFFFFFFF0
    
    call find_kernel32_funcs_64
    mov rcx, -11
    mov rax, [get_std_handle_address]
    call rax
    mov qword [rsp + 0x28], 0
    mov rcx, rax
    lea rdx, [hello_world]
    mov r8, hello_world_len
    lea r9, [hole]
    mov rax, [write_console_address]
    call rax
    
    mov rsp, rbp
    pop r11
    pop r9
    pop r8
    pop rdx
    pop rcx
    pop rax
    pop rbp
    ret
    Ответить
    • find_kernel32_funcs_64:
      push rax
      push rbx
      push rcx
      push rdx
      push rsi
      push rdi
      push r11
      push r8
      push r9
      
      lea rcx, [kernel32_namew]
      call find_loaded_module_64
      mov rdx, rax
      
      mov rdx, [rdx + 0x30] ;module->base / DOS_HEADER
      mov rcx, rdx
      mov qword [kernel32_handle], rcx
      
      mov r11d, dword [rdx + 0x3C]
      add rdx, r11          ;base + dos_hdr->e_lfanew / NT_HEADER
      mov r11d, dword [rdx + 0x88]
      lea rdx, [rcx + r11]  ;base + exports table RVA
      
      mov ebx, dword [rdx + 0x20]  ;AddressOfNames RVA
      lea rsi, [rcx + rbx]
      mov ebx, dword [rdx + 0x24]  ;AddressOfNameOrdinals RVA
      lea rdi, [rcx + rbx]
      mov ebx, dword [rdx + 0x1C]  ;AddressOfFunctions RVA
      lea rbx, [rcx + rbx]
      
      mov r11, rcx ;dll base
      mov rcx, 2  ;number of functions
      
      find_kernel32_funcs_64_loop:
      mov edx, dword [rsi] ;RVA
      add rdx, r11    ;name = base + *namePtr
      
      ;WriteConsole
      write_console_check:
      cmp qword [write_console_address], 0
      jnz get_std_handle_check
      
      push rcx
      lea rcx, [write_console_name]
      call strcmp64
      pop rcx
      
      cmp rax,0
      jne get_std_handle_check
      
      ;found proc
      push rcx
      push rdx
      lea rcx, [write_console_address]
      mov rdx, rdi
      mov r8, rbx
      mov r9, r11
      call load_export_64
      pop rdx
      pop rcx
      
      dec rcx
      jmp find_kernel32_funcs_64_loop_post_check
      
      ;GetStdHandle
      get_std_handle_check:
      cmp qword [get_std_handle_address], 0
      jnz find_kernel32_funcs_64_loop_post_check
      
      push rcx
      lea rcx, [get_std_handle_name]
      call strcmp64
      pop rcx
      
      cmp rax,0
      jne find_kernel32_funcs_64_loop_post_check
      
      ;found proc
      push rcx
      push rdx
      lea rcx, [get_std_handle_address]
      mov rdx, rdi
      mov r8, rbx
      mov r9, r11
      call load_export_64
      pop rdx
      pop rcx
      
      dec rcx
      
      find_kernel32_funcs_64_loop_post_check:
      cmp rcx, 0
      je find_kernel32_funcs_64_loop_end
      add rsi, 4
      add rdi, 2
      jmp find_kernel32_funcs_64_loop
      
      find_kernel32_funcs_64_loop_end:
      
      pop r9
      pop r8
      pop r11
      pop rdi
      pop rsi
      pop rdx
      pop rcx
      pop rbx
      pop rax
      ret
      Ответить
      • find_loaded_module_64:
        push rdx
        push rbx
        push r11
        
        mov r11, rcx
        
        db 0x65,0x48,0x8B,0x14,0x25,0x60,0x00,0x00,0x00 ;mov rdx, qword [gs:0x60]
        mov rdx, [rdx + 0x18] ;mdllist
        mov rdx, [rdx + 0x18] ;mlink: LDR_MODULE
        mov rcx, rdx ;mlink
        
        find_loaded_module_64_loop:
        mov rdx, [rdx]
        cmp dword [rdx + 0x30], 0 ;module->base != 0
        je find_loaded_module_64_loop
        
        push rdx
        push rcx
        mov rcx, r11
        mov rdx, [rdx+0x60]   ;module->dllName.Buffer
        call strilcmp64w
        pop rcx
        pop rdx
        
        cmp rax,0
        je find_loaded_module_64_loop_end
        
        cmp rdx, rcx
        jne find_loaded_module_64_loop
        
        find_loaded_module_64_loop_end:
        mov rax, rdx
        
        pop r11
        pop rbx
        pop rdx
        ret
        strcmp64:
        sub rsp, 0x10
        push rbx
        
        mov rax, rcx
        mov rbx, rdx
        
        strcmp64_loop:
        cmp byte [rax], 0
        je strcmp64_exit
        cmp byte [rbx], 0
        je strcmp64_exit
        
        mov cl, [rbx]
        cmp [rax], cl
        jne strcmp64_exit
        inc rax
        inc rbx
        jmp strcmp64_loop
        
        strcmp64_exit:
        mov al, [rax]
        sub al, [rbx]
        and rax, 0xFF
        
        pop rbx
        add rsp, 0x10
        ret
        
        strilcmp64w:
        sub rsp, 0x10
        push rbx
        
        mov rax, rcx
        mov rbx, rdx
        
        strilcmp64w_loop:
        cmp word [rax], 0
        je strilcmp64w_exit
        cmp word [rbx], 0
        je strilcmp64w_exit
        
        mov cx, [rbx]
        or cx, 0x20
        cmp [rax], cx
        jne strilcmp64w_exit
        add rax, 2
        add rbx, 2
        jmp strilcmp64w_loop
        
        strilcmp64w_exit:
        mov ax, [rax]
        sub ax, [rbx]
        and rax, 0xFFFF
        
        pop rbx
        add rsp, 0x10
        ret
        
        load_export_64:
        sub rsp, 0x20
        push rdi
        push rax
        
        xor rax, rax
        mov ax, word [rdx] ;*ordinal
        shl rax, 2     ;*ordinal * 4
        add rax, r8   ;*ordinal * 4 + base + exportsDir->AddressOfFunctions
        mov eax, dword [rax] ;RVA
        add rax, r9  ;dll base
        
        mov qword [rcx], rax
        
        pop rax
        pop rdi
        add rsp, 0x20
        ret
        Ответить
        • А что за асм такой хуёвый что приходится юзать db для банального mov?
          Ответить
          • Какая-то из версий «Fasm'а» почему-то конпелировала «mov rdx, qword [gs:0x60]» в херню. Или я неправильно что-то делал, забыл уже за давностью лет.
            Ответить

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

Я, guest, находясь в здравом уме и твердой памяти, торжественно заявляю:

    А не использовать ли нам bbcode?


    8