flat assembler
Message board for the users of flat assembler.

Index > Tutorials and Examples > FASMG Hello World Dalvik

Author
Thread Post new topic Reply to topic
MaoKo



Joined: 07 May 2019
Posts: 100
Location: Paris/French
MaoKo 17 Nov 2020, 03:24
Hello. This is a simple POC of an Hello World on android with the dalvik vm.
Code:

format binary as "dex"
org $00

macro _assert_unsigned? list?*&
    iterate item?*, list
        assert (item >= $00)
    end iterate
end macro

macro byte? list?*&
    db list
end macro

macro ubyte? list?*&
    _assert_unsigned list
    db list
end macro

macro short? list?*&
    db list
end macro

macro ushort? list?*&
    _assert_unsigned list
        dw list
end macro

macro int? list?*&
        dd list
end macro

macro uint? list?*&
    _assert_unsigned list
        dd list
end macro

macro long? list?*&
    dq list
end macro

macro ulong? list?*&
    _assert_unsigned list
    dq list
end macro

macro leb128? list?*& ; uleb128 & sleb128
    local value?, least?, more?
    iterate item?*, list
        value? = item
        more? = $01
        while (more)
            least? = value and $7F
            value? = value shr $07
            more? = $00
            if ~ ((value = $00) | ((value = -$01) & (least = $7F)))
                least? = least or $80
                more? = $01
            end if
            db least
        end while
    end iterate
end macro

struc _rotate_left? size?*, expression?*, amount?*
    local bitmask?, shift?, select?, offset?
    _assert_unsigned size, amount
    . = (expression)
    shift? = (amount) mod (size)
    select? = (($01 shl (size)) - $01)
    if (shift)
        offset? = (size) - shift
        bitmask? = ((((($01 shl amount) - $01) shl offset) and .) shr offset)
        . = (((. shl amount) and select) or bitmask)
    end if
end struc

struc sha1? payload?*
    local container?, size?, chunk?, block?, max32?, temporary?
    local h0?, h1?, h2?, h3?, h4?
    local a?, b?, c?, d?, e?, f?, k?
    h0? = $67452301
    h1? = $EFCDAB89
    h2? = $98BADCFE
    h3? = $10325476
    h4? = $C3D2E1F0
    size? = lengthof payload
    chunk? = $00
    max32? := $FFFFFFFF
    virtual at $00
    container?::
        db payload, $80
        emit (($40 - (($ + $08) mod $40)) mod $40) : $00
        dq (size * $08) bswap $08
        size? = $
    end virtual
    while (chunk < size)
        load block? : $40 from container:chunk
        repeat $10 i:$00
            local w#i?
            w#i? = ((block shr ($20 * i)) and max32) bswap $04
        end repeat
        repeat $40 i:$10, im03:$0D, im08:$08, im0E:$02, im10:$00
            local w#i?
            w#i? _rotate_left $20, (w#im03) xor (w#im08) xor (w#im0E) xor (w#im10), $01
        end repeat
        a? = h0
        b? = h1
        c? = h2
        d? = h3
        e? = h4
        repeat $50 i:$00
            if (i <= $13)
                f? = (b and c) or (((not b) and max32) and d)
                k? = $5A827999
            else if (i <= $27)
                f? = (b xor c xor d)
                k? = $6ED9EBA1
            else if (i <= $3B)
                f? = ((b and c) or (b and d) or (c and d))
                k? = $8F1BBCDC
            else
                f? = (b xor c xor d)
                k? = $CA62C1D6
            end if
            temporary? _rotate_left $20, a, $05
            temporary? = ((temporary + f + e + k + w#i) and max32)
            e? = d
            d? = c
            c? _rotate_left $20, b, $1E
            b? = a
            a? = temporary
        end repeat
        h0? = ((h0 + a) and max32)
        h1? = ((h1 + b) and max32)
        h2? = ((h2 + c) and max32)
        h3? = ((h3 + d) and max32)
        h4? = ((h4 + e) and max32)
        chunk? = chunk + $40
    end while
    . = ((h4) or (h3 shl $20) or (h2 shl $40) or (h1 shl $60) or (h0 shl $80))
end struc

struc adler32? payload?*
    local modulo?, a?, b?
    modulo? := $FFF1
    a? = $01
    b? = $00
    repeat (lengthof (payload)) i:$00
        a? = (a? + ((payload shr (i*$08)) and $FF)) mod modulo
        b? = (b? + a?) mod modulo
    end repeat
    . = (b shl $10) or a
end struc

macro align? target?*, fill?:$00
    _assert_unsigned target
    assert ((bsr target) = (bsf target))
    while ($ mod target)
        db fill
    end while
end macro

macro __define_index? base?*
    base := $00
    base.index? = $00
end macro

macro __update_index? target?*, base?*
    target = base.index?
    base.index? = base.index? + $01
end macro

macro __snapshot_index? target?*, base?*
    target := base.index?
end macro

DEX_FILE_MAGIC? := $6465780A30333500 bswap $08
ENDIAN_CONSTANT? := $12345678
REVERSE_ENDIAN_CONSTANT? := $78563412
NO_INDEX? := $FFFFFFFF

__define_index __string_id_item?

struc string_id_item? _string_data_off?*
    __update_index ., __string_id_item?
    align $04
    .string_data_off?: uint _string_data_off
end struc

__define_index __type_id_item?

struc type_id_item? _descriptor_idx?*
    __update_index ., __type_id_item?
    align $04
    .descriptor_idx?: uint _descriptor_idx
end struc

__define_index __proto_id_item?

struc proto_id_item? _shorty_idx?*, _return_type_idx?*, _parameters_off?*
    __update_index ., __proto_id_item?
    align $04
        .shorty_idx?: uint _shorty_idx
        .return_type_idx?: uint _return_type_idx
        .parameters_off?: uint _parameters_off
end struc

__define_index __field_id_item?

struc field_id_item? _class_idx?*, _type_idx?*, _name_idx?*
    __update_index ., __field_id_item?
    align $04
        .class_idx?: ushort _class_idx
        .type_idx?: ushort _type_idx
        .name_idx?: uint _name_idx
end struc

__define_index __method_id_item?

struc method_id_item? _class_idx?*, _proto_idx?*, _name_idx?*
    __update_index ., __method_id_item?
    align $04
    .class_idx?: ushort _class_idx
        .proto_idx?: ushort _proto_idx
        .name_idx?: uint _name_idx
end struc

ACC_PUBLIC?             := $000001
ACC_PRIVATE?            := $000002
ACC_PROTECTED?          := $000004
ACC_STATIC?             := $000008
ACC_FINAL?              := $000010
ACC_NATIVE?             := $000100
ACC_INTERFACE?          := $000200
ACC_ABSTRACT?           := $000400
ACC_ANNOTATION?         := $002000
ACC_ENUM?               := $004000
ACC_CONSTRUCTOR?        := $010000

__define_index __class_def_item?

struc class_def_item?           _class_idx?*, _access_flags?*, _superclass_idx?*, _interfaces_off?*,\
                                _source_file_idx?*, _annotations_off?*, _class_data_off?*, _static_values_off?*
    __update_index ., __class_def_item?
    align $04
    .class_idx?: uint _class_idx
    .access_flags?: uint _access_flags
    .superclass_idx?: uint _superclass_idx
    .interfaces_off?: uint _interfaces_off
    .source_file_idx?: uint _source_file_idx
    .annotations_off?: uint _annotations_off
    .class_data_off?: uint _class_data_off
    .static_values_off?: uint _static_values_off
end struc

struc type_item? _type_idx?*
        .type_idx?: ushort _type_idx
end struc

struc type_list? _size?*, _list?*
    align $04
    label .
        .size?: uint _size
    .list?:
    iterate item?, _list
        .list?.% type_item item
    end iterate
end struc

TYPE_HEADER_ITEM?           := $0000
TYPE_STRING_ID_ITEM?        := $0001
TYPE_TYPE_ID_ITEM?          := $0002
TYPE_PROTO_ID_ITEM?         := $0003
TYPE_FIELD_ID_ITEM?         := $0004
TYPE_METHOD_ID_ITEM?        := $0005
TYPE_CLASS_DEF_ITEM?        := $0006
TYPE_CALL_SITE_ID_ITEM?     := $0007
TYPE_METHOD_HANDLE_ITEM?    := $0008
TYPE_MAP_LIST?              := $1000
TYPE_TYPE_LIST?             := $1001
TYPE_CLASS_DATA_ITEM?       := $2000
TYPE_CODE_ITEM?             := $2001
TYPE_STRING_DATA_ITEM?      := $2002

struc map_list? _size?*, _list?
    align $04
    label .
    .size?: uint _size
    .list?:
    iterate item?, _list
        .list?.% map_item item
    end iterate
end struc

struc map_item? _type?*, _size?*, _offset?*
    .type?: ushort _type
    ushort $00
    .size?: uint _size
    .offset?: uint _offset
end struc

struc string_data_item? _utf16_size?*, _data?&
    label .
    .utf16_size?: leb128 _utf16_size
    .data?: ubyte _data, $00
end struc

struc class_data_item?          _static_fields_size?*, _instance_fields_size?*, _direct_methods_size?*, _virtual_methods_size?*,\
                                _static_fields?, _instance_fields?, _direct_methods?, _virtual_methods?
    label .
    .static_fields_size?: leb128 _static_fields_size
    .instance_fields_size?: leb128 _instance_fields_size
    .direct_methods_size?: leb128 _direct_methods_size
    .virtual_methods_size?: leb128 _virtual_methods_size
    .static_fields?:
    iterate static_field?, _static_fields
        .static_fields?.% encoded_field static_field
    end iterate
    .instance_fields?:
    iterate instance_field?, _instance_fields
        .instance_fields?.% encoded_field instance_field
    end iterate
    .direct_methods?:
    iterate direct_method?, _direct_methods
        .direct_methods?.% encoded_method direct_method
    end iterate
    .virtual_methods?:
    iterate virtual_method?, _virtual_methods
        .virtual_methods?.% encoded_method virtual_method
    end iterate
end struc

struc encoded_field? _field_idx_diff?*, access_flags?*
    .field_idx_diff?: leb128 _field_idx_diff
    .access_flags?: leb128 _access_flags
end struc

struc encoded_method? _method_idx_diff?*, _access_flags?*, _code_off?*
    .method_idx_diff?: leb128 _method_idx_diff
    .access_flags?: leb128 _access_flags
    .code_off?: leb128 _code_off
end struc

struc code_item? _registers_size?*, _ins_size?*, _outs_size?*, _tries_size?*, _debug_info_off?*, _insns_size?*, _insns?*
    local base?, size?, opcode?
    align $04
    label .
    .registers_size?: ushort _registers_size
    .ins_size?: ushort _ins_size
    .outs_size?: ushort _outs_size
    .tries_size?: ushort _tries_size
    .debug_info_off?: uint _debug_info_off
    virtual _insns
        base? = $$
        size? =  $ - $$
    end virtual
    assert ~ (size and $01)
    size? = size shr $01
    if (size > _insns_size)
        size? = _insns_size
    end if
    load opcode? : (size shl $01) from _insns:base
    .insns_size?: uint size
    .insns?: db opcode
    if (_tries_size)
        align $04
        .tries?:
        .handlers?:
    end if
end struc

struc try_item? _start_addr?*, _insn_count?*, _handler_off?*
    .start_addr?: uint _start_addr
    .insn_count?: ushort _insn_count
    .handler_off?: ushort _handler_off
end struc

postpone
__global::

    header:
        ubyte DEX_FILE_MAGIC
    header_magic_end:
        uint $00
    header_adler32:
        emit $14: $00
    header_sha1:
        uint (header_end - header) ; file_size
        uint (string_ids - header) ; header_size
        uint ENDIAN_CONSTANT ; endian_tag
        uint $00 ; link_size
        uint $00 ; link_off
        uint _map ; map_off
        uint string_ids_size
        uint (string_ids - header) ; string_ids_off
        uint type_ids_size
        uint (type_ids - header) ; type_ids_off
        uint proto_ids_size
        uint (proto_ids - header) ; proto_ids_off
        uint field_ids_size
        uint (field_ids - header) ; field_ids_off
        uint method_ids_size
        uint (method_ids - header) ; method_ids_off
        uint class_defs_size
        uint (class_defs - header) ; class_defs_off
        uint (link_data - data) ; data_size
        uint (data - header) ; data_off

    string_ids:
        _hello_string string_id_item _hello_data
        _class_hello_name_string string_id_item _class_hello_name_data
        _java_lang_print_stream_string string_id_item _java_lang_print_stream_data
        _java_lang_object_string string_id_item _java_lang_object_data
        _string_string string_id_item _string_data
        _java_lang_system_string string_id_item _java_lang_system_data
        _void_string string_id_item _void_data
        _class_hello_main_shorty_string string_id_item _class_hello_main_shorty_data
        _main_argument_1_string string_id_item _main_argument_1_data
        _main_string string_id_item _main_data
        _out_string string_id_item _out_data
        _println_string string_id_item _println_data

    type_ids:
        _class_hello_type type_id_item _class_hello_name_string
        _java_lang_print_stream_type type_id_item _java_lang_print_stream_string
        _java_lang_object_type type_id_item _java_lang_object_string
        _string_type type_id_item _string_string
        _java_lang_system_type type_id_item _java_lang_system_string
        _void_type type_id_item _void_string
        _array_string_type type_id_item _main_argument_1_string

    proto_ids:
        _println_proto proto_id_item _class_hello_main_shorty_string, _void_type, _println_type_list
        _main_proto proto_id_item _class_hello_main_shorty_string, _void_type, _main_type_list

    field_ids:
        _out_system_field field_id_item _java_lang_system_type, _java_lang_print_stream_type, _out_string

    method_ids:
        _class_hello_main_method method_id_item _class_hello_type, _main_proto, _main_string
        _println_method method_id_item _java_lang_print_stream_type, _println_proto, _println_string

    class_defs:
        _class_hello_class class_def_item _class_hello_type, ACC_PUBLIC, _java_lang_object_type, $00, NO_INDEX, $00, _class_hello_data, $00

    call_site_ids:
    method_handles:

    data:
        data_string_data_item:
            _hello_data string_data_item                    $05, "HELLO"
            _class_hello_name_data string_data_item         $0C, "LHelloWorld;"
            _java_lang_print_stream_data string_data_item   $15, "Ljava/io/PrintStream;"
            _java_lang_object_data string_data_item         $12, "Ljava/lang/Object;"
            _string_data string_data_item                   $12, "Ljava/lang/String;"
            _java_lang_system_data string_data_item         $12, "Ljava/lang/System;"
            _void_data string_data_item                     $01, "V"
            _class_hello_main_shorty_data string_data_item  $02, "VL"
            _main_argument_1_data string_data_item          $13, "[Ljava/lang/String;"
            _main_data string_data_item                     $04, "main"
            _out_data string_data_item                      $03, "out"
            _println_data string_data_item                  $07, "println"

        align $04

        data_type_list:
            _main_type_list type_list $01, <_array_string_type>
            _println_type_list type_list $01, <_string_type>

        align $04

        data_class_data_item:
            _class_hello_data class_data_item $00, $00, $01, $00,\
                <>,\
                <>,\
                <<_class_hello_main_method, ACC_PUBLIC or ACC_STATIC, _class_hello_code_data>>,\
                <>

        align $04

        data_code_item:
            _class_hello_code_data code_item $02, $01, $02, $00, $00, $08, _class_hello_code

        align $04

        data_map_list:
            _map map_list $0C, <\
                    <TYPE_HEADER_ITEM, $01, header>,\
                    <TYPE_STRING_ID_ITEM, string_ids_size, string_ids>,\
                    <TYPE_TYPE_ID_ITEM, type_ids_size, type_ids>,\
                    <TYPE_PROTO_ID_ITEM, proto_ids_size, proto_ids>,\
                    <TYPE_FIELD_ID_ITEM, field_ids_size, field_ids>,\
                    <TYPE_METHOD_ID_ITEM, method_ids_size, method_ids>,\
                    <TYPE_CLASS_DEF_ITEM, class_defs_size, class_defs>,\
                    <TYPE_STRING_DATA_ITEM, $0C, data_string_data_item>,\
                    <TYPE_TYPE_LIST, $02, data_type_list>,\
                    <TYPE_CLASS_DATA_ITEM, $01, data_class_data_item>,\
                    <TYPE_CODE_ITEM, $01, data_code_item>,\
                    <TYPE_MAP_LIST, $01, data_map_list>,\
                >

        align $04
        
    link_data:

    header_end:

        __snapshot_index string_ids_size, __string_id_item
        __snapshot_index type_ids_size, __type_id_item
        __snapshot_index proto_ids_size, __proto_id_item
        __snapshot_index field_ids_size, __field_id_item        
        __snapshot_index method_ids_size, __method_id_item
        __snapshot_index class_defs_size, __class_def_item

        assert (type_ids_size <= $FFFF)

    load payload : ($ - header_sha1) from __global : header_sha1
    sha1_payload sha1 payload

    store sha1_payload : $14 at __global : header_adler32

    load payload : ($ - header_adler32) from __global : header_adler32
    adler32_payload adler32 payload
 
    store adler32_payload : $04 at __global : header_magic_end
   
end postpone

virtual at $00
_class_hello_code::
    dw $0062, _out_system_field         ; sget-object v0, _out_system_field
    dw $011A, _hello_string             ; const-string v1, _hello_string
    dw $206E, _println_method, $0010    ; invoke-virtual {v0,v1}, _println_method
    dw $000E                            ; return-void
end virtual
    


To compile and launch it:
Code:
$ fasmg hello.inc classes.dex
$ zip HelloWorld.apk classes.dex
$ adb push HelloWorld.apk /mnt/sdcard
$ adb shell dalvikvm -cp /mnt/sdcard/HelloWorld.apk HelloWorld
    
Post 17 Nov 2020, 03:24
View user's profile Send private message Visit poster's website Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 802
Location: Russian Federation, Sochi
ProMiNick 17 Nov 2020, 16:14
cool. but syntax I dislike.
could thou provide more examples?
dw $0062,...
dw $011A,...
dw $206E,...
dw $000E, ...
they are opcodes of dalvic virtual CPU? (word CPU is incorrect. dalvic VM)
Post 17 Nov 2020, 16:14
View user's profile Send private message Send e-mail Reply with quote
MaoKo



Joined: 07 May 2019
Posts: 100
Location: Paris/French
MaoKo 18 Nov 2020, 00:49
ProMiNick wrote:

could thou provide more examples?

Yes. I would like to create a windowed hello world. But this is far more complex than this.
I need to create an activity and manifest ...
But first, I need to arrange some macro.

ProMiNick wrote:

dw $0062,...
dw $011A,...
dw $206E,...
dw $000E, ...
they are opcodes of dalvic virtual CPU? (word CPU is incorrect. dalvic VM)


Yes. I follow this source for the opcode encoding.
https://source.android.com/devices/tech/dalvik/dalvik-bytecode
I've not created instructions macro because dalvik instructions contain "-" and "/" character.
This is why I defined the raw opcode directly.
I need to create a ?! macro that do that parsing.
Post 18 Nov 2020, 00:49
View user's profile Send private message Visit poster's website Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 802
Location: Russian Federation, Sochi
ProMiNick 18 Nov 2020, 01:38
opcodes - not contain "-" and "/" character. it is in their suffixes.
such suffixes could be parsed analogipusly as size operator in x86 I guess. so no needance in ?!
but that allow syntaxes as
move - wide / from16 vAA, vBBBB
where suffixes splited by numerous spaces.
arg1 equ - wide / from16 vAA
arg2 equ some_expression
thou will need to parse arg1 to determine opcode modifiers.
fasm forum is not good place to post links to resources on rus language (I understand, but here are many peoples that would preffer docs in english).
Post 18 Nov 2020, 01:38
View user's profile Send private message Send e-mail Reply with quote
FlierMate



Joined: 21 Jan 2021
Posts: 219
FlierMate 20 May 2022, 09:57
I followed your nice example, but the HELLO string is displayed on my PC terminal window, not on Android device. Hmm....

Code:
C:\fasmg>adb push test.apk /storage/emulated/0/
test.apk: 1 file pushed, 0 skipped. 0.8 MB/s (482 bytes in 0.001s)    


Code:
C:\fasmg>adb shell dalvikvm -cp /storage/emulated/0/test.apk HelloWorld
HELLO    


Description:
Filesize: 11.74 KB
Viewed: 6002 Time(s)

Screenshot 2022-05-20 175534.png


Post 20 May 2022, 09:57
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-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.