AngeloD2022 / jsxer

Jsxer is a fast and accurate decompiler for Adobe ExtendScript Binary (JSXBIN) files, featuring JSXBlind deobfuscation.
GNU General Public License v3.0
157 stars 25 forks source link

Commit breaks decompilation #51

Closed WeedyWeedSmoker closed 1 year ago

WeedyWeedSmoker commented 1 year ago

Commit 51f884bce01dd7d37c99b7717b69ee8ff9bf648d breaks decompilation of some more complex jsxbin scripts with a segmentation fault

AngeloD2022 commented 1 year ago

Could you email me an example of the file(s) that it segfaults with?

WeedyWeedSmoker commented 1 year ago

@AngeloD2022 Ok! I just sent you an e-mail…

AngeloD2022 commented 1 year ago

@AngeloD2022 Ok! I just sent you an e-mail…

Alright, I will check it out in a bit. Thanks.

AngeloD2022 commented 1 year ago

The script you sent me does seem to hit a weird edge case at some point, but it doesn't seem to involve the commit you suggested (at least according to my very quick examination).

The script completes decompilation successfully, but something goes horribly wrong when the jsxer::decompile function exits.

CleanShot 2022-10-23 at 14 57 25@2x

I managed to fix it by replacing...

Reader reader(input, jsxblind_deobfuscate);

with this...

Reader *reader = new Reader(input, jsxblind_deobfuscate);

I am not sure what the consequences of this change are for decompile performance, but the change seems to fix the segmentation fault.

WeedyWeedSmoker commented 1 year ago

@AngeloD2022 I should have mentioned I use a compiled binary on a Mac…

Trying your fix breaks the compilation as a binary with these errors:

Building CXX object CMakeFiles/jsxer-core.dir/src/jsxer/jsxer.cpp.o
jsxbin_decompiler/src/jsxer/jsxer.cpp:67:16: error: member reference type 'jsxer::Reader *' is a pointer; did you mean to use '->'?
    if (!reader.verifySignature()) {
         ~~~~~~^
               ->
jsxbin_decompiler/src/jsxer/jsxer.cpp:75:13: error: no matching constructor for initialization of 'jsxer::nodes::Program'
    Program ast(reader);
            ^   ~~~~~~
jsxbin_decompiler/src/jsxer/nodes/Program.h:11:18: note: candidate constructor not viable: no known conversion from 'jsxer::Reader *' to 'jsxer::Reader &' for 1st argument; dereference the argument with *
        explicit Program(Reader& reader) : AstNode(reader) {}
                 ^
jsxbin_decompiler/src/jsxer/nodes/Program.h:9:11: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'jsxer::Reader *' to 'const jsxer::nodes::Program' for 1st argument
    class Program : AstNode {
          ^
jsxbin_decompiler/src/jsxer/nodes/Program.h:9:11: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'jsxer::Reader *' to 'jsxer::nodes::Program' for 1st argument
2 errors generated.
make[2]: *** [CMakeFiles/jsxer-core.dir/src/jsxer/jsxer.cpp.o] Error 1
make[1]: *** [CMakeFiles/jsxer-core.dir/all] Error 2
make: *** [all] Error 2
AngeloD2022 commented 1 year ago

Use the branch: issue-51

WeedyWeedSmoker commented 1 year ago

@AngeloD2022 Ok, I just tested the issue-51 branch, but it still segfaults on the script I sent you (when using a compiled binary on Mac)…

The last commit that didn't segfault for me was the one before 51f884b

AngeloD2022 commented 1 year ago

Looks like we have a "works on my machine" scenario.

AngeloD2022 commented 1 year ago

Mind specifying architectural details about your machine, operating system, etc? Also helps to show the stack trace of the segfault if you open it in LLDB.

WeedyWeedSmoker commented 1 year ago

macOS 11.7 Intel cpu, I'm not so sure how to open it in LLDB…

I can try to Google it but if you know how I could test that I'll happily take some instructions!

WeedyWeedSmoker commented 1 year ago

I got that output from LLDB, but I'm not sure if it's helpful (I don't know if having debug symbols would help?)

0x7fff206acf3c <+0>: nop
0x7fff206acf3d <+1>: movl %eax, %edi Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT) 0x7fff206acf3f <+3>: callq 0x7fff206c9784 ; symbol stub for: exit 0x7fff206acf44 <+8>: hlt

WeedyWeedSmoker commented 1 year ago

Here is the complete stack: (error at 0x1060038ea)

jsxer`jsxer::nodes::ListExpression::to_string:
    0x1060037e0 <+0>:   pushq  %rbp
    0x1060037e1 <+1>:   movq   %rsp, %rbp
    0x1060037e4 <+4>:   subq   $0xe0, %rsp
    0x1060037eb <+11>:  movq   %rdi, -0xd0(%rbp)
    0x1060037f2 <+18>:  movq   %rdi, %rcx
    0x1060037f5 <+21>:  movq   %rcx, -0xc8(%rbp)
    0x1060037fc <+28>:  movq   %rdi, -0x8(%rbp)
    0x106003800 <+32>:  movq   %rsi, -0x10(%rbp)
    0x106003804 <+36>:  movq   -0x10(%rbp), %rcx
    0x106003808 <+40>:  movq   %rcx, -0xc0(%rbp)
    0x10600380f <+47>:  movb   $0x0, -0x11(%rbp)
    0x106003813 <+51>:  callq  0x106003b20               ; std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string()
    0x106003818 <+56>:  leaq   0x31636(%rip), %rsi       ; ", "
    0x10600381f <+63>:  leaq   -0x30(%rbp), %rdi
    0x106003823 <+67>:  callq  0x106003b40               ; std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string<std::nullptr_t>(char const*)
    0x106003828 <+72>:  jmp    0x10600382d               ; <+77>
    0x10600382d <+77>:  movl   $0x0, -0x40(%rbp)
    0x106003834 <+84>:  movq   -0xc0(%rbp), %rdi
    0x10600383b <+91>:  movslq -0x40(%rbp), %rax
    0x10600383f <+95>:  movq   %rax, -0xd8(%rbp)
    0x106003846 <+102>: addq   $0x10, %rdi
    0x10600384a <+106>: callq  0x106003b70               ; std::__1::vector<jsxer::nodes::AstNode*, std::__1::allocator<jsxer::nodes::AstNode*> >::size() const
    0x10600384f <+111>: movq   %rax, %rcx
    0x106003852 <+114>: movq   -0xd8(%rbp), %rax
    0x106003859 <+121>: cmpq   %rcx, %rax
    0x10600385c <+124>: jae    0x106003a0d               ; <+557>
    0x106003862 <+130>: movq   -0xc0(%rbp), %rax
    0x106003869 <+137>: testb  $0x1, 0x28(%rax)
    0x10600386d <+141>: je     0x1060038cd               ; <+237>
    0x106003873 <+147>: cmpl   $0x0, -0x40(%rbp)
    0x106003877 <+151>: jle    0x1060038cd               ; <+237>
    0x10600387d <+157>: movq   -0xc0(%rbp), %rdi
    0x106003884 <+164>: addq   $0x10, %rdi
    0x106003888 <+168>: movslq -0x40(%rbp), %rsi
    0x10600388c <+172>: callq  0x106003b90               ; std::__1::vector<jsxer::nodes::AstNode*, std::__1::allocator<jsxer::nodes::AstNode*> >::operator[](unsigned long)
    0x106003891 <+177>: movq   %rax, %rcx
    0x106003894 <+180>: movq   (%rcx), %rdi
    0x106003897 <+183>: movl   $0x1, %esi
    0x10600389c <+188>: callq  0x1060054a0               ; jsxer::nodes::LocalAssignmentExpression::suppress_declarative_keyword(bool)
    0x1060038a1 <+193>: jmp    0x1060038a6               ; <+198>
    0x1060038a6 <+198>: jmp    0x1060038cd               ; <+237>
    0x1060038ab <+203>: movq   %rax, %rcx
    0x1060038ae <+206>: movl   %edx, %eax
    0x1060038b0 <+208>: movq   %rcx, -0x38(%rbp)
    0x1060038b4 <+212>: movl   %eax, -0x3c(%rbp)
    0x1060038b7 <+215>: jmp    0x106003afc               ; <+796>
    0x1060038bc <+220>: movq   %rax, %rcx
    0x1060038bf <+223>: movl   %edx, %eax
    0x1060038c1 <+225>: movq   %rcx, -0x38(%rbp)
    0x1060038c5 <+229>: movl   %eax, -0x3c(%rbp)
    0x1060038c8 <+232>: jmp    0x106003ad2               ; <+754>
    0x1060038cd <+237>: movq   -0xc0(%rbp), %rdi
    0x1060038d4 <+244>: addq   $0x10, %rdi
    0x1060038d8 <+248>: movslq -0x40(%rbp), %rsi
    0x1060038dc <+252>: callq  0x106003b90               ; std::__1::vector<jsxer::nodes::AstNode*, std::__1::allocator<jsxer::nodes::AstNode*> >::operator[](unsigned long)
    0x1060038e1 <+257>: movq   %rax, %rcx
    0x1060038e4 <+260>: movq   (%rcx), %rsi
    0x1060038e7 <+263>: movq   (%rsi), %rcx
->  0x1060038ea <+266>: movq   0x8(%rcx), %rcx `Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)`
    0x1060038ee <+270>: leaq   -0x70(%rbp), %rdi
    0x1060038f2 <+274>: callq  *%rcx
    0x1060038f4 <+276>: jmp    0x1060038f9               ; <+281>
    0x1060038f9 <+281>: movq   -0xc0(%rbp), %rdi
    0x106003900 <+288>: movl   -0x40(%rbp), %eax
    0x106003903 <+291>: addl   $0x1, %eax
    0x106003906 <+294>: cltq   
    0x106003908 <+296>: movq   %rax, -0xe0(%rbp)
    0x10600390f <+303>: addq   $0x10, %rdi
    0x106003913 <+307>: callq  0x106003b70               ; std::__1::vector<jsxer::nodes::AstNode*, std::__1::allocator<jsxer::nodes::AstNode*> >::size() const
    0x106003918 <+312>: movq   %rax, %rcx
    0x10600391b <+315>: movq   -0xe0(%rbp), %rax
    0x106003922 <+322>: cmpq   %rcx, %rax
    0x106003925 <+325>: jne    0x106003948               ; <+360>
    0x10600392b <+331>: leaq   0x31466(%rip), %rsi       ; ""
    0x106003932 <+338>: leaq   -0x88(%rbp), %rdi
    0x106003939 <+345>: callq  0x106003b40               ; std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string<std::nullptr_t>(char const*)
    0x10600393e <+350>: jmp    0x106003943               ; <+355>
    0x106003943 <+355>: jmp    0x106003962               ; <+386>
    0x106003948 <+360>: leaq   -0x88(%rbp), %rdi
    0x10600394f <+367>: leaq   -0x30(%rbp), %rsi
    0x106003953 <+371>: callq  0x106032406               ; symbol stub for: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
    0x106003958 <+376>: jmp    0x10600395d               ; <+381>
    0x10600395d <+381>: jmp    0x106003962               ; <+386>
    0x106003962 <+386>: leaq   -0x58(%rbp), %rdi
    0x106003966 <+390>: leaq   -0x70(%rbp), %rsi
    0x10600396a <+394>: leaq   -0x88(%rbp), %rdx
    0x106003971 <+401>: callq  0x106003bb0               ; std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > std::__1::operator+<char, std::__1::char_traits<char>, std::__1::allocator<char> >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
    0x106003976 <+406>: jmp    0x10600397b               ; <+411>
    0x10600397b <+411>: movq   -0xd0(%rbp), %rdi
    0x106003982 <+418>: leaq   -0x58(%rbp), %rsi
    0x106003986 <+422>: callq  0x106003c00               ; std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::operator+=(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
    0x10600398b <+427>: jmp    0x106003990               ; <+432>
    0x106003990 <+432>: leaq   -0x58(%rbp), %rdi
    0x106003994 <+436>: callq  0x106032412               ; symbol stub for: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()
    0x106003999 <+441>: leaq   -0x88(%rbp), %rdi
    0x1060039a0 <+448>: callq  0x106032412               ; symbol stub for: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()
    0x1060039a5 <+453>: leaq   -0x70(%rbp), %rdi
    0x1060039a9 <+457>: callq  0x106032412               ; symbol stub for: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()
    0x1060039ae <+462>: movl   -0x40(%rbp), %eax
    0x1060039b1 <+465>: addl   $0x1, %eax
    0x1060039b4 <+468>: movl   %eax, -0x40(%rbp)
    0x1060039b7 <+471>: jmp    0x106003834               ; <+84>
    0x1060039bc <+476>: movq   %rax, %rcx
    0x1060039bf <+479>: movl   %edx, %eax
    0x1060039c1 <+481>: movq   %rcx, -0x38(%rbp)
    0x1060039c5 <+485>: movl   %eax, -0x3c(%rbp)
    0x1060039c8 <+488>: jmp    0x1060039ff               ; <+543>
    0x1060039cd <+493>: movq   %rax, %rcx
    0x1060039d0 <+496>: movl   %edx, %eax
    0x1060039d2 <+498>: movq   %rcx, -0x38(%rbp)
    0x1060039d6 <+502>: movl   %eax, -0x3c(%rbp)
    0x1060039d9 <+505>: jmp    0x1060039f3               ; <+531>
    0x1060039de <+510>: movq   %rax, %rcx
    0x1060039e1 <+513>: movl   %edx, %eax
    0x1060039e3 <+515>: movq   %rcx, -0x38(%rbp)
    0x1060039e7 <+519>: movl   %eax, -0x3c(%rbp)
    0x1060039ea <+522>: leaq   -0x58(%rbp), %rdi
    0x1060039ee <+526>: callq  0x106032412               ; symbol stub for: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()
    0x1060039f3 <+531>: leaq   -0x88(%rbp), %rdi
    0x1060039fa <+538>: callq  0x106032412               ; symbol stub for: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()
    0x1060039ff <+543>: leaq   -0x70(%rbp), %rdi
    0x106003a03 <+547>: callq  0x106032412               ; symbol stub for: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()
    0x106003a08 <+552>: jmp    0x106003ad2               ; <+754>
    0x106003a0d <+557>: movq   -0xc0(%rbp), %rax
    0x106003a14 <+564>: testb  $0x1, 0x29(%rax)
    0x106003a18 <+568>: je     0x106003ab6               ; <+726>
    0x106003a1e <+574>: movq   -0xc0(%rbp), %rax
    0x106003a25 <+581>: testb  $0x1, 0x28(%rax)
    0x106003a29 <+585>: jne    0x106003ab6               ; <+726>
    0x106003a2f <+591>: movq   -0xd0(%rbp), %rdx
    0x106003a36 <+598>: leaq   -0xb8(%rbp), %rdi
    0x106003a3d <+605>: movl   $0x28, %esi
    0x106003a42 <+610>: callq  0x10603261c               ; symbol stub for: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > std::__1::operator+<char, std::__1::char_traits<char>, std::__1::allocator<char> >(char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
    0x106003a47 <+615>: jmp    0x106003a4c               ; <+620>
    0x106003a4c <+620>: leaq   -0xa0(%rbp), %rdi
    0x106003a53 <+627>: leaq   -0xb8(%rbp), %rsi
    0x106003a5a <+634>: movl   $0x29, %edx
    0x106003a5f <+639>: callq  0x106003c30               ; std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > std::__1::operator+<char, std::__1::char_traits<char>, std::__1::allocator<char> >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, char)
    0x106003a64 <+644>: jmp    0x106003a69               ; <+649>
    0x106003a69 <+649>: movq   -0xd0(%rbp), %rdi
    0x106003a70 <+656>: leaq   -0xa0(%rbp), %rsi
    0x106003a77 <+663>: callq  0x106003c80               ; std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::operator=(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
    0x106003a7c <+668>: leaq   -0xa0(%rbp), %rdi
    0x106003a83 <+675>: callq  0x106032412               ; symbol stub for: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()
    0x106003a88 <+680>: leaq   -0xb8(%rbp), %rdi
    0x106003a8f <+687>: callq  0x106032412               ; symbol stub for: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()
    0x106003a94 <+692>: jmp    0x106003ab6               ; <+726>
    0x106003a99 <+697>: movq   %rax, %rcx
    0x106003a9c <+700>: movl   %edx, %eax
    0x106003a9e <+702>: movq   %rcx, -0x38(%rbp)
    0x106003aa2 <+706>: movl   %eax, -0x3c(%rbp)
    0x106003aa5 <+709>: leaq   -0xb8(%rbp), %rdi
    0x106003aac <+716>: callq  0x106032412               ; symbol stub for: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()
    0x106003ab1 <+721>: jmp    0x106003ad2               ; <+754>
    0x106003ab6 <+726>: movb   $0x1, -0x11(%rbp)
    0x106003aba <+730>: leaq   -0x30(%rbp), %rdi
    0x106003abe <+734>: callq  0x106032412               ; symbol stub for: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()
    0x106003ac3 <+739>: testb  $0x1, -0x11(%rbp)
    0x106003ac7 <+743>: jne    0x106003aec               ; <+780>
    0x106003acd <+749>: jmp    0x106003ae0               ; <+768>
    0x106003ad2 <+754>: leaq   -0x30(%rbp), %rdi
    0x106003ad6 <+758>: callq  0x106032412               ; symbol stub for: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()
    0x106003adb <+763>: jmp    0x106003afc               ; <+796>
    0x106003ae0 <+768>: movq   -0xd0(%rbp), %rdi
    0x106003ae7 <+775>: callq  0x106032412               ; symbol stub for: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()
    0x106003aec <+780>: movq   -0xc8(%rbp), %rax
    0x106003af3 <+787>: addq   $0xe0, %rsp
    0x106003afa <+794>: popq   %rbp
    0x106003afb <+795>: retq   
    0x106003afc <+796>: movq   -0xd0(%rbp), %rdi
    0x106003b03 <+803>: callq  0x106032412               ; symbol stub for: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()
    0x106003b08 <+808>: movq   -0x38(%rbp), %rdi
    0x106003b0c <+812>: callq  0x10603229e               ; symbol stub for: _Unwind_Resume
    0x106003b11 <+817>: nopw   %cs:(%rax,%rax)
    0x106003b1b <+827>: nopl   (%rax,%rax)
AngeloD2022 commented 1 year ago

This is a weird issue. Could you perhaps tell me what version of clang and LLVM you are using?

WeedyWeedSmoker commented 1 year ago

Using the default Command Line Tools for Xcode 13.2 (with Xcode 13.2.1)

clang:

Apple clang version 13.0.0 (clang-1300.0.29.30)
Target: x86_64-apple-darwin20.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

LLVM: llvm-gcc seems to just call clang so it's the same version…

AngeloD2022 commented 1 year ago

Sorry, took a small break from maintaining the project. I will continue to look into this.

AngeloD2022 commented 1 year ago

Can you try this out with the latest commit?

WeedyWeedSmoker commented 1 year ago

Can you try this out with the latest commit?

From the test files I sent you, TypeX_v1.5.53.jsxbin decompiles fine now but orionx.jsx still throws an error:

libc++abi: terminating with uncaught exception of type std::out_of_range: stoi: out of range
zsh: abort      ./jsxer /orionx.jsx /orionxdec.jsx
AngeloD2022 commented 1 year ago

Latest commit fixed your issue! :)

WeedyWeedSmoker commented 1 year ago

Latest commit fixed your issue! :)

Seems not to be fixed using a mac executable then, still errors with:

[i] Decompiling...
libc++abi: terminating with uncaught exception of type std::out_of_range: stoi: out of range
terminating with uncaught exception of type std::out_of_range: stoi: out of range
(lldb) 

libsystem_kernel.dylib`__pthread_kill: 0x7fff204bf914 <+0>: movl $0x2000148, %eax ; imm = 0x2000148 0x7fff204bf919 <+5>: movq %rcx, %r10 0x7fff204bf91c <+8>: syscall -> 0x7fff204bf91e <+10>: jae 0x7fff204bf928 ; <+20> <- error Thread 1: signal SIGABRT 0x7fff204bf920 <+12>: movq %rax, %rdi 0x7fff204bf923 <+15>: jmp 0x7fff204b9ac9 ; cerror_nocancel 0x7fff204bf928 <+20>: retq
0x7fff204bf929 <+21>: nop
0x7fff204bf92a <+22>: nop
0x7fff204bf92b <+23>: nop

libdyld.dylib`start: 0x7fff20509f3c <+0>: nop
-> 0x7fff20509f3d <+1>: movl %eax, %edi <- error Thread 1: signal SIGABRT 0x7fff20509f3f <+3>: callq 0x7fff20526784 ; symbol stub for: exit 0x7fff20509f44 <+8>: hlt

AngeloD2022 commented 1 year ago

Damn. That's a real head-scratcher. The orionx script fully decompiles for me.

WeedyWeedSmoker commented 1 year ago

Damn. That's a real head-scratcher. The orionx script fully decompiles for me.

Oh you're right it's fixed!

Somehow the latest release's source code is not fixed yet, but just compiling from the main source works!

AngeloD2022 commented 1 year ago

Yeah, this is my fault lol. I also have another related fix that I forgot to commit.