Menu

The input chunk reports an unsupported instruction size: 8 bytes

EtoNeTimur
2025-02-28
2025-03-04
  • EtoNeTimur

    EtoNeTimur - 2025-02-28

    hello, I tried to decompile a .lua binary file but I failed because of size_of_Instruction. I understand your program doesn't support 0x08 bytes?
    Source of compiled lua file: https://github.com/Tencent/UnLua.

     

    Last edit: tehtmi 2025-02-28
  • tehtmi

    tehtmi - 2025-02-28

    1.

    Non-standard header prevents parsing. Insert byte (hex) 08 between offset 0C and offset 0D (containing 04 04). Or; modify unluac to expect this header.

    diff -r 9cfa7b28ab36 src/unluac/parse/LHeaderType.java
    --- a/src/unluac/parse/LHeaderType.java Fri Dec 27 14:54:51 2024 -0800
    +++ b/src/unluac/parse/LHeaderType.java Thu Feb 27 23:29:24 2025 -0800
    @@ -418,7 +418,8 @@
         parse_format(buffer, header, s);
         parse_tail(buffer, header, s);
         parse_int_size(buffer, header, s);
    -    parse_size_t_size(buffer, header, s);
    +    //parse_size_t_size(buffer, header, s);
    +    s.sizeT = new BIntegerType50(false, 8, false);
         parse_instruction_size(buffer, header, s);
         parse_integer_size(buffer, header, s);
         parse_float_size(buffer, header, s);
    

    (Build of current head with this patch attached.)

    2.

    Non-standard op encodings, needs to use unluac's --opmap option with the correct opmap file. I can usually decode the ops that appear in the sample with only a little guessing. (E.g. lt and le can be tricky to distinguish from only context.) Files using other ops won't work unless you add them (or if I'm nice enough to help again; usually I don't mind decoding opmaps).

    .op 1 lt
    .op 9 self
    .op 11 eq
    .op 12 sub
    .op 14 call
    .op 15 test
    .op 21 tforloop
    .op 22 gettable
    .op 23 newtable
    .op 38 gettabup
    .op 39 loadk
    .op 40 closure
    .op 41 move
    .op 42 loadnil
    .op 44 jmp
    .op 46 settable
    .op 49 getupval
    .op 52 return
    .op 54 tforcall
    .op 58 add
    .op 59 loadbool
    

    3.

    Someone posted UnLua before, but it was 5.4; this is 5.3. That also had a non-standard chunk format. I didn't see any of the non-standard stuff reflected in the github repo, so I didn't even bother to look this time. Maybe just custom, not sure. Probably not helpful, but for reference, here.

     

    Last edit: tehtmi 2025-02-28
  • EtoNeTimur

    EtoNeTimur - 2025-03-02

    Sorry it took me so long to reply, the script works, but not all files are decrypted, so I've uploaded an archive in which I found unknown opcodes and files that contain these unknown opcodes. If you don't have enough examples for a certain opcode, let me know.
    I think UnLua is confusing opcodes, because I don't see any logic in them.

     
  • tehtmi

    tehtmi - 2025-03-02

    I think it's mostly okay. I switched lt and le (still hard to tell apart). bnot is a wild guess. It seems like it is either a meta-op invocation which I have found no context for in which case it is probably still unary, so bnot or I suppose unm by process of elimination, maybe taking the address or returning an ID; or I guess maybe it could be a custom op; or I'm just blanking on something, but it doesn't seem like there's many options (it almost certainly writes to register A, and is almost certainly unary or nullary, and probably results in a number when the parameter if any is not a number). It's not doing anything particularly interesting here, I don't think. Here it will decompile as bnot (or unm), so...

    .op 1 le
    .op 2 band
    .op 7 tailcall
    .op 8 not
    .op 9 self
    .op 11 eq
    .op 12 sub
    .op 13 div
    .op 14 call
    .op 15 test
    .op 16 shl
    .op 17 settabup
    .op 18 forprep
    .op 19 mod
    .op 20 testset
    .op 21 tforloop
    .op 22 gettable
    .op 23 newtable
    .op 24 idiv
    .op 34 bnot
    .op 38 gettabup
    .op 39 loadk
    .op 40 closure
    .op 41 move
    .op 42 loadnil
    .op 43 forloop
    .op 44 jmp
    .op 45 setlist
    .op 46 settable
    .op 47 concat
    .op 48 setupval
    .op 49 getupval
    .op 50 len
    .op 51 lt
    .op 52 return
    .op 54 tforcall
    .op 55 shr
    .op 56 mul
    .op 58 add
    .op 59 loadbool
    
     

    Last edit: tehtmi 2025-03-02
  • EtoNeTimur

    EtoNeTimur - 2025-03-03

    Hi, I've uploaded an archive where all missing opcodes are located, the names indicate which opcode they are and their number.
    I also added files with a lot of bnot opcodes. Thanks for the work you have done.

     
  • tehtmi

    tehtmi - 2025-03-03

    Some are non-standard ops. For example op34 is an increment operation, like C's ++. I think there's also a +=. I can write a patch to unluac for at least some of these (haven't finished looking), but I thought I'd ask what semantics would be most useful for you? I could decompile using custom operators (probably matching C's where possible; -- couldn't be used if that comes up...) which represents the binary more precisely (and I think is most likely to be the original semantics), but then can't be compiled by a normal Lua compiler; or I could decompile into the equivalent Lua.

    -- option 1
    x++
    x += f()
    -- option 2
    x = x + 1
    x = x + f()
    

    (It's weird to implement these features as custom ops, but best I can tell that's what's happening. Anyway, there are certainly more opcode bytes in use than are needed for standard Lua 5.3.)

     

    Last edit: tehtmi 2025-03-04
  • tehtmi

    tehtmi - 2025-03-04

    Yeah, interesting. I still think this is a really silly way to implement this feature...

    It looks like just ++ and +=, but different ops for the target being local vs table member vs upvalue (and by the opmap pattern, we could guess maybe there are tabup versions as well but I didn't bother implementing those yet), although not all combinations are observed.

    Patch and build decompiling via ++and +=, but it would be easy to convert to normal Lua too (although, frankly, probably easy to do by hand as well...). Maybe a bit awkward if you care about re-evaluating the target which probably doesn't really matter in these files anyway.

    .op 0 bxor
    .op 1 le
    .op 2 band
    .op 3 unm
    .op 4 pow
    .op 7 tailcall
    .op 8 not
    .op 9 self
    .op 10 vararg
    .op 11 eq
    .op 12 sub
    .op 13 div
    .op 14 call
    .op 15 test
    .op 16 shl
    .op 17 settabup
    .op 18 forprep
    .op 19 mod
    .op 20 testset
    .op 21 tforloop
    .op 22 gettable
    .op 23 newtable
    .op 24 idiv
    .op 31 tabaddeq
    .op 34 inc
    .op 35 tabinc
    .op 36 upinc
    .op 38 gettabup
    .op 39 loadk
    .op 40 closure
    .op 41 move
    .op 42 loadnil
    .op 43 forloop
    .op 44 jmp
    .op 45 setlist
    .op 46 settable
    .op 47 concat
    .op 48 setupval
    .op 49 getupval
    .op 50 len
    .op 51 lt
    .op 52 return
    .op 53 bnot
    .op 54 tforcall
    .op 55 shr
    .op 56 mul
    .op 57 bor
    .op 58 add
    .op 59 loadbool
    
     

    Last edit: tehtmi 2025-03-04

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.