Tag: computers

  • Chastity Windows Reverse Engineering Notes

    The Windows version of FASM includes header files for the Windows API. It also includes some examples, but not a single one of them were a simple “Hello World” console program.

    Fortunately, I was able to find one that actually assembled and ran on the FASM forum. Below is the source code.

    format PE console
    include 'win32ax.inc'
    .code
    start:
    invoke  WriteConsole, <invoke GetStdHandle,STD_OUTPUT_HANDLE>,"Hello World!",12,0
    invoke  ExitProcess,0
    .end start
    

    To get it working required me to keep the include files in a location I remembered and set the include environment variable. I found this out from the FASM Windows documentation.

    set include=C:\fasm\INCLUDE

    However, there was another problem. The example that I found online and got working uses macros, most specifically, one called “invoke”. While this works if you include the headers, it hides the details of what is actually happening. Therefore, I decided to reverse engineer the process by using NOP instructions to sandwich the bytes of machine code.

    90 hex is the byte for NOP (No OPeration). So to extract the macro call that exits the program, I use this.

    db 10h dup 90h
    invoke  ExitProcess,0
    db 10h dup 90h
    

    Then I disassemble the executable and find the actual instructions given.

    ndisasm main.exe -b 32 > disasm.txt

    As simple as this method is, it actually works. For example, this output is given as part of the output.

    0000022D  90                nop
    0000022E  90                nop
    0000022F  90                nop
    00000230  90                nop
    00000231  90                nop
    00000232  90                nop
    00000233  90                nop
    00000234  90                nop
    00000235  90                nop
    00000236  90                nop
    00000237  90                nop
    00000238  90                nop
    00000239  90                nop
    0000023A  90                nop
    0000023B  90                nop
    0000023C  90                nop
    0000023D  6A00              push dword 0x0
    0000023F  FF1548204000      call dword near [0x402048]
    00000245  90                nop
    00000246  90                nop
    00000247  90                nop
    00000248  90                nop
    00000249  90                nop
    0000024A  90                nop
    0000024B  90                nop
    0000024C  90                nop
    0000024D  90                nop
    0000024E  90                nop
    0000024F  90                nop
    00000250  90                nop
    00000251  90                nop
    00000252  90                nop
    00000253  90                nop
    00000254  90                nop
    

    There can be no mistake that it is that location between the NOPs where the relevant code is. Therefore, I replaced the macro that exits the program with this.

    ;Exit the process with code 0
     push 0
     call [ExitProcess]
    

    What I learned

    As I repeated the same process for the other macros, I found that the way system calls in Windows work is that the numbers are pushed onto the stack in the reverse order they are needed. I was able to decode the macros and get a working program without the use of “invoke”. Here is the full source!

    format PE console
    include 'win32ax.inc'
    
    main:
    
    ;Write 13 bytes from a string to standard output
    push 0              ;this must be zero. I have no idea why!  
    push 13             ;number of bytes to write
    push main_string    ;address of string to print
    push -11            ;STD_OUTPUT_HANDLE = Negative Eleven
    call [GetStdHandle] ;use the above handle
    push eax            ;eax is return value of previous function
    call [WriteConsole] ;all the data is in place, do the write thing!
    
    ;Exit the process with code 0
    push 0
    call [ExitProcess]
    
    .end main
    
    main_string db 'Hello World!',0Ah
    

    I don’t know much about the Windows API, but I did discover some helpful information when I searched the names of these functions that were part of the original macros.

    https://learn.microsoft.com/en-us/windows/console/getstdhandle
    https://learn.microsoft.com/en-us/windows/console/writeconsole

    Why I did this

    You might wonder why I even bothered to get a working Windows API program in Assembly Language. After all, I am a Linux user to the extreme. However, since Windows is the most used operating system for the average person, I figured that if I write any useful programs in Assembly for 32-bit Linux, I can probably port them over to Windows by changing just a few things.

    Since my toy programs are designed to write text to the console anyway and I don’t do GUI stuff unless I am programming a game in C with SDL, I now have enough information from this small Hello World example to theoretically write anything to the console that I might want to in an official Windows executable.

    Obviously I need to learn a lot more for bigger programs but this is the first Assembly program I have ever gotten working for Windows, despite my great success with DOS and Linux, which are easier because they are better documented and ARE TAUGHT BETTER by others. People programming Assembly in Windows have been ruined by macros which hide the actual instructions being used. As I learn how these things work, I will be sure to pass on the information to others!

  • DOS Assembly putstring function

    This is a small program which uses the putstring function I wrote. This function is one of 4 ultimate functions I have created which make up “chastelib”. DOS programming is simpler than Windows and is not that different from Linux in that system calls are done with an interrupt.

    org 100h
    
    main:
    
    mov ax,text
    call putstring
    
    mov ax,4C00h
    int 21h
    
    text db 'Hello World!',0Dh,0Ah,0
    
    ;This section is for the putstring function I wrote.
    ;It will print any zero terminated string that register ax points to
    
    stdout dw 1 ; variable for standard output so that it can theoretically be redirected
    
    putstring:
    
    push ax
    push bx
    push cx
    push dx
    
    mov bx,ax                  ;copy ax to bx for use as index register
    
    putstring_strlen_start:    ;this loop finds the length of the string as part of the putstring function
    
    cmp [bx], byte 0           ;compare this byte with 0
    jz putstring_strlen_end    ;if comparison was zero, jump to loop end because we have found the length
    inc bx                     ;increment bx (add 1)
    jmp putstring_strlen_start ;jump to the start of the loop and keep trying until we find a zero
    
    putstring_strlen_end:
    
    sub bx,ax                  ; sub ax from bx to get the difference for number of bytes
    mov cx,bx                  ; mov bx to cx
    mov dx,ax                  ; dx will have address of string to write
    
    mov ah,40h                 ; select DOS function 40h write 
    mov bx,[stdout]            ; file handle 1=stdout
    int 21h                    ; call the DOS kernel
    
    pop dx
    pop cx
    pop bx
    pop ax
    
    ret
    

    Anyone can assemble and run this source code, but you will need a DOS emulator like DOSBox in order for it to work. In fact, I have a video showing me assembling and running it inside of DOSBox.

    Lately I have been having a programming phase and am working on a book about programming in DOS. There is no money involved in this because nobody except nerds like me care about DOS. Speaking of nerds, if you follow my blog, don’t forget that this site was set up for teaching Chess. Leave me a comment if you play Chess online or live in Lee’s Summit. I am still playing Chess every day although some of my time has been taken up with programming in Assembly language because it is so much fun.

    If you like this post, you may be interested in my much longer post/book that is all about Assembly programming in DOS.

  • Assembly Chaste Lib

    I have created two functions in x86 Assembly Language that allow me to output any zero terminated string or output any integer in any base from 2 to 36. I will show the full source so people can play with it. This uses system calls on Linux so it won’t work on Windows.

    first, the header file “chaste-lib.asm”

    ; This file is where I keep my function definitions.
    ; These are usually my string and integer output routines.
    
    putstring: ; function to print zero terminated string pointed to by register eax
    
    mov edx,eax ; copy eax to edx as well. Now both registers have the address of the main_string
    
    strlen_start: ; this loop finds the lenge of the string as part of the putstring function
    
    cmp [edx],byte 0 ; compare byte at address edx with 0
    jz strlen_end ; if comparison was zero, jump to loop end because we have found the length
    inc edx
    jmp strlen_start
    
    strlen_end:
    sub edx,eax ; edx will now have correct number of bytes when we use it for the system write call
    
    mov ecx,eax ; copy eax to ecx which must contain address of string to write
    mov eax, 4  ; invoke SYS_WRITE (kernel opcode 4)
    ;mov ebx, 1  ; ebx=1 means write to the STDOUT file
    int 80h     ; system call to write the message
    
    ret ; this is the end of the putstring function return to calling location
    
    
    
    
    
    
    radix dd 16 ;radix or base for integer output. 2=binary, 16=hexadecimal, 10=decimal
    
    putint: ; function to output decimal form of whatever integer is in eax
    
    push eax ;save eax on the stack to restore later
    
    mov ebp,int_string+31 ;address of start digits
    
    digits_start:
    
    mov edx,0;
    mov esi,[radix] ;radix is from memory location just before this function
    div esi
    cmp edx,10
    jb decimal_digit
    jge hexadecimal_digit
    
    decimal_digit: ;we go here if it is only a digit 0 to 9
    add edx,'0'
    jmp save_digit
    
    hexadecimal_digit:
    sub edx,10
    add edx,'A'
    
    
    save_digit:
    
    mov [ebp],dl
    cmp eax,0
    jz digits_end
    dec ebp
    jmp digits_start
    
    digits_end:
    
    mov eax,ebp ; now that the digits have been written to the string, display it!
    call putstring
    
    pop eax  ;load eax from the stack so it will be as it was before this function was called
    ret
    

    next, the main source that includes the header: “main.asm”

    format ELF executable
    entry main
    
    include 'chaste-lib.asm'
    
    main: ; the main function of our assembly function, just as if I were writing C.
    
    ; I can load any string address into eax and print it!
    
    mov ebx, 1 ;ebx must be 1 to write to standard output
    
    mov eax,msg
    call putstring
    mov eax,main_string ; move the address of main_string into eax register
    call putstring
    
    mov [radix],2 ; can choose radix for integer output!
    
    mov eax,0
    loop1:
    call putint
    inc eax
    cmp eax,100h;
    jnz loop1
    
    mov eax, 1  ; invoke SYS_EXIT (kernel opcode 1)
    mov ebx, 0  ; return 0 status on exit - 'No Errors'
    int 80h
    
    ; this is where I keep my string variables
    
    msg db 'Hello World!', 0Ah,0     ; assign msg variable with your message string
    main_string db "This is Chastity's Assembly Language counting program!",0Ah,0
    int_string db 32 dup '?',0Ah,0
    
    
    
    ; This Assembly source file has been formatted for the FASM assembler.
    ; The following 3 commands assemble, give executable permissions, and run the program
    ;
    ;	fasm main.asm
    ;	chmod +x main
    ;	./main
    
    

    If you have the fasm compiler, you can assemble this source on any Linux distribution running on an intel CPU. Assembly is platform specific but it runs really fast and the process of programming with it is enjoyable for me.