metasploit-framework icon indicating copy to clipboard operation
metasploit-framework copied to clipboard

[shellcode, stager] ARM stager restore r0 in loop

Open enty8080 opened this issue 1 year ago • 5 comments

r0 has return value instead of sockfd in second loop iteration

After first iteration r0 is filled with recv() return code, however we expect it to have sockfd for the next iteration, otherwise recv() will attempt to read from bad file descriptor (aka return value of previous recv() call)

It might require to modify stager inside modules directory.

enty8080 avatar Aug 05 '24 21:08 enty8080

There might be the same problem with linux/armle/bind_tcp

enty8080 avatar Aug 05 '24 22:08 enty8080

Thanks for the pull request!

Is this PR related to this issue? https://github.com/rapid7/metasploit-framework/issues/16107 :eyes:

adfoster-r7 avatar Aug 06 '24 09:08 adfoster-r7

@adfoster-r7 I just looked through this issue. It might be related to this (reading from bad file descriptor causes segfault).

We also need to reassemble shellcode from external directory and put it to modules/payload/stager/linux/armle/reverse_tcp.rb. As you can see in this PR I only modified source code of shellcode and applied a small change to ruby payload, however I think I made a mistake and we need to recalculate the location where payload jumps (inside the read loop). It is quite difficult to modify payload when we only have machine code. I think using metasm to assemble code right on payload generation will simplify the modification of the payload without the need to recompile it every time. (Some metasploit payloads use metasm though)

P.S. I am currently working on creating an alternative platform in Python (like Metasploit) and store all payloads in assembly code and then invoke assembler on them only when user needs it. - You can take a look at it here - https://github.com/EntySec/HatSploit/blob/main/hatsploit/payloads/single/linux/x64/shell_reverse_tcp.py

enty8080 avatar Aug 06 '24 09:08 enty8080

metasm isn't always viable/reliable, but if it is - that works for me :+1:

In the scenarios were metasm isn't viable, which is an issue we ran into with the osx aarch64 payloads that landed recentlyish - we added a quick pipe of objdump to ruby to grab out the hex representation and comments, example: https://github.com/rapid7/metasploit-framework/pull/17129/files#diff-23f0b96528cb168853ac403470d4c09a500213b5b39d82fff073a04eab42aac0R1-R2 - it might be possible to follow suit with this pattern so it's easier to change the payloads again in the future

adfoster-r7 avatar Aug 06 '24 14:08 adfoster-r7

@adfoster-r7 I have an idea. You can actually use keystone-engine instead of metasm. It seems more advanced and powerful and supports most of the CPU architectures. I used it to write shellcodes for macOS too and on M1 (arm64) it works well. I compiled few sources from external directory here and they seem to work just fine. In fact, my tool that I mentioned above where I store all payloads in assembly and then assemble them in keystone-engine has no issues with this approach.

enty8080 avatar Aug 08 '24 10:08 enty8080

@dledda-r7 Thank you for detailed explanation, I see where I made a mistake. I've just changed this instruction in payload.

enty8080 avatar Dec 18 '24 07:12 enty8080

Release Notes

This fixes the ARM stager to properly download the second stage by fixing the recv() loop

dledda-r7 avatar Jan 06 '25 16:01 dledda-r7