flat assembler
Message board for the users of flat assembler.

Index > Compiler Internals > [solved] Addition bug in fasm 1.73.31

Author
Thread Post new topic Reply to topic
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 18 Oct 2023, 19:05
I am trying to report a bug but when I upload the sources I get " Tried to upload empty file"
Post 18 Oct 2023, 19:05
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20454
Location: In your JS exploiting you and your system
revolution 18 Oct 2023, 19:08
Describe your bug here, in text. You can use [code] and [/code] tags also.
Post 18 Oct 2023, 19:08
View user's profile Send private message Visit poster's website Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 18 Oct 2023, 19:57
I create an image to be booted by a bootloader (floppy, hard disk, pxe, uefi).
I calculate a 32 bit checksum of all the dwords of the image, using a repeat loop with load dword temp32bit from ... and RunningSum=(RunningSum -temp32bit) and 0xffffffff.
This way the entire sum including the checksum is 0.
If I do this in the first 212 (this number varies and depends on the data) dwords of the image, it works fine.
If I go further, the checksum is augmented by 0x100, so that the total sum equals 0x100.
If I run the sum through all the image, the error becomes 0x01000000.

I don't have the code here, I will post the assembler and assembly snippets.

I sent an email to Thomasz, it would be great if he could post the email text and attachment.
Post 18 Oct 2023, 19:57
View user's profile Send private message Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 18 Oct 2023, 20:40
Assembler snippet:
Code:
        align   4
RunningSum = 0
NumRep=212
REPEAT  NumRep;$% / 4
        LOAD Temp32bit DWord FROM $$ + (% - 1) * 4
        RunningSum = (RunningSum - Temp32bit) And 0xFFFFFFFF
END REPEAT
        dd      RunningSum      ;Checksum

ProgSize        = $%
    


Assembly snippet:
Code:
        xor     eax, eax
        mov     fs, ax                          ;fs and gs are not used
        mov     gs, ax
;Initialize memory with 0s where needed
        mov     ecx, BSS0size
        mov     edi, BSS0start
        rep     stosb
;Compute checksum right at the start, to allow subsequent modifications in
;the data loaded from disk which would cause the check to fail
        mov     ecx, NumRep;ProgSize / 4
@@:
        add     eax, [$$ + (ecx - 1) * 4]
        loop    @b
add eax, [$$ + ProgSize - 4]
        mov     [ComputedSum], eax
    


Both snippets are modified with NumRep for testing purposes.
Post 18 Oct 2023, 20:40
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20454
Location: In your JS exploiting you and your system
revolution 18 Oct 2023, 21:32
The value of org will affect the address of [$$ + ProgSize - 4]. perhaps you meant this
Code:
ProgSize        = $ - $$    
Post 18 Oct 2023, 21:32
View user's profile Send private message Visit poster's website Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 18 Oct 2023, 21:47
Yes, org affects that expression and does it right, because the code is executed at the right place, starting at 0x100200.

$-$$ in my case is the same as $%

You can modify these expressions as you wish: the first must point to the last dword of the image, the second must hold the number of bytes (multiple of 4).
This is why I was trying to post the full source, so that these expressions would certainly be correct.
Post 18 Oct 2023, 21:47
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20454
Location: In your JS exploiting you and your system
revolution 18 Oct 2023, 21:52
If $$ == 0x100200
then ProgSize == 0x100200 + 212*4 == 0x1002D4
then [$$ + ProgSize - 4] == [0x100200 + 0x100200 + 212 * 4 - 4] == [0x2004D0]
Post 18 Oct 2023, 21:52
View user's profile Send private message Visit poster's website Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 19 Oct 2023, 00:00
No. NumRep has nothing to do with ProgSize. It just for testing: the running sum only takes into account the first NumRep dwords of the image, to see when and how the error comes in. You play with NumRep in order to understand the bug.
That is why I added "add eax, [$$+ProgSize-4]": it picks the last dword (the checksum), what is normally not needed when the sum runs over the entire image.

Also, note that ProgSize has nothing to do with the org at 100200,, as it is just the number of bytes of the image.
$% gives an offset in the data, not an address.
Post 19 Oct 2023, 00:00
View user's profile Send private message Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 19 Oct 2023, 00:18
Anyway, if I can't post the full source, it doesn't make sense to reason on the assembler address symbols.
Just do a 32bit checksum of an image in the same way I did, and see the problem by changing the span of the sum: you don't need to copy the exact details of my code.
Post 19 Oct 2023, 00:18
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20454
Location: In your JS exploiting you and your system
revolution 19 Oct 2023, 00:32
We don't know what you have done. Please post a minimal working example showing the problem. There is no need to post full source, just a handful of lines.
Post 19 Oct 2023, 00:32
View user's profile Send private message Visit poster's website Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 19 Oct 2023, 02:26
Here are 3 tests.
In each there is the image main1.bin (which differs in every test), and a test program that calculates the checksum. In the comment there are the values calculated (that you can see looking at the last dword of the output) which are wrong in the first two tests by 0x01000000.


Description:
Download
Filename: tests.7z
Filesize: 467.78 KB
Downloaded: 169 Time(s)

Post 19 Oct 2023, 02:26
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20454
Location: In your JS exploiting you and your system
revolution 19 Oct 2023, 03:12
I agree with the fasm computation.

t.asm
Code:
;       cat test1/test.asm ; echo ; fasm -d DWORDS=213 -d NAME="'test1/main1.bin'" t.asm && ./t
;       cat test2/test.asm ; echo ; fasm -d DWORDS=212 -d NAME="'test2/main1.bin'" t.asm && ./t
;       cat test3/test.asm ; echo ; fasm -d DWORDS=200 -d NAME="'test3/main1.bin'" t.asm && ./t

format elf executable

SYS32_read              = 3
SYS32_write             = 4
SYS32_open              = 5
SYS32_exit_group        = 252
STDOUT_FILENO           = 1
O_RDONLY                = 00o
MIN_ERROR               = -4095

hex_table:      db '0123456789abcdef'
file_name       db NAME,0
length  =       DWORDS * 4

buffer rb length

entry $
        mov     eax,SYS32_open
        mov     ebx,file_name
        mov     ecx,O_RDONLY
        xor     edx,edx         ; mode
        int     0x80
        mov     bl,2
        cmp     eax,MIN_ERROR
        jae     quit
        ;
        mov     ebx,eax
        mov     eax,SYS32_read
        mov     ecx,buffer
        mov     edx,length
        int     0x80
        mov     bl,3
        cmp     eax,MIN_ERROR
        jae     quit
        mov     esi,eax
        ;
        xor     eax,eax
        mov     ecx,length shr 2
    .loop:
        add     eax,dword[buffer + (ecx - 1) * 4]
        loop    .loop
        neg     eax
        call    print_hex8
        mov     dl,10
        call    print_char
        mov     bl,0
quit:   mov     eax,SYS32_exit_group
        movzx   ebx,bl
        int     0x80


print_hex8:
        ;rax = value
        push    ebx eax ecx edx
        mov     ecx,8
        lea     ebx,[hex_table]
    .next_nibble:
        rol     eax,4
        mov     edx,eax
        and     edx,0xf
        mov     dl,[ebx + edx]
        call    print_char
        dec     ecx
        jnz     .next_nibble
        pop     edx ecx eax ebx
        ret

print_char:
        ;dl = character
        push    eax ecx ebx edx
        mov     eax,SYS32_write
        mov     ebx,STDOUT_FILENO
        mov     ecx,esp
        mov     edx,1
        int     0x80
        pop     edx ebx ecx eax
        ret    
Output log
Code:
~ cat test1/test.asm ; echo ; fasm -d DWORDS=213 -d NAME="'test1/main1.bin'" t.asm && ./t
file 'main1.bin':0,213*4

RunningSum = 0
REPEAT  $% / 4
        LOAD Temp32bit DWord FROM $$ + (% - 1) * 4
        RunningSum = (RunningSum - Temp32bit) And 0xFFFFFFFF
END REPEAT
        dd      RunningSum      ;Computes and stores 0x2249DB9C instead of 0x2149DB9C
flat assembler  version 1.73.31  (16384 kilobytes memory)
2 passes, 1135 bytes.
2249db9c
~ cat test2/test.asm ; echo ; fasm -d DWORDS=212 -d NAME="'test2/main1.bin'" t.asm && ./t
file 'main1.bin':0,212*4

RunningSum = 0
REPEAT  $% / 4
        LOAD Temp32bit DWord FROM $$ + (% - 1) * 4
        RunningSum = (RunningSum - Temp32bit) And 0xFFFFFFFF
END REPEAT
        dd      RunningSum      ;Computes and stores 0xBC4ADB9C instead of 0xBB4ADB9C
flat assembler  version 1.73.31  (16384 kilobytes memory)
2 passes, 1131 bytes.
bc4adb9c
~ cat test3/test.asm ; echo ; fasm -d DWORDS=200 -d NAME="'test3/main1.bin'" t.asm && ./t
file 'main1.bin':0,200*4

RunningSum = 0
REPEAT  $% / 4
        LOAD Temp32bit DWord FROM $$ + (% - 1) * 4
        RunningSum = (RunningSum - Temp32bit) And 0xFFFFFFFF
END REPEAT
        dd      RunningSum      ;Computes and stores 0x7A52DE09 correctly
flat assembler  version 1.73.31  (16384 kilobytes memory)
2 passes, 1083 bytes.
7a52de09
~    
Post 19 Oct 2023, 03:12
View user's profile Send private message Visit poster's website Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 19 Oct 2023, 05:39
It was my fault, sorry.

The snippet I use to compute the sum runs after loading DS/ES with a descriptor having the access bit reset. This descriptor is obviously part of the checksummed data.
As soon as the memory is accessed, the CPU turns that bit on, thus changing the data over which the sum runs, by just one bit.
Then the sum differs by 1 bit, compared to the original one.

Setting the access bit in the data descriptor solves the problem.
Post 19 Oct 2023, 05:39
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.