Closed hypnoticpattern closed 4 years ago
I can verify I have the same issue. The binary launcher file references /System/Library/Frameworks/Python.framework/Versions/2.7/Python
. I am unsure how those files were created to begin with, but I think having one that targets 2.7 and another to target 3.x might be the solution, what do you think?
I floated a similar idea here https://github.com/BC-SECURITY/Empire/issues/81#issuecomment-578002801
It would be great to have the templates source code, either creating new ones or retrieving the source for the the ones embedded in the project, since it can be useful to make sure nothing funky is happening when you run the binary.
To keep things simple I would stick with the current version of the app because Python 2.7 ships with MacOS and we can rely on the fact that it is on all MacOS systems. At least until Apple decides to migrate to Python 3.x. That being said for my current situation would be perfect to have both apps: one that references to Python 2.7 and another one to Python 3.7.
I moved one step forward using this tip importing standard libraries before line 443
launcherBase += "from future.standard_library import install_aliases;\n"
launcherBase += "install_aliases();\n"
Unfortunately that wouldn't make the code work with Python 3 out of the box (same as issue 81)
Digging into the problem I found another porting bug related to the stage1 sent to the MacOS:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 22, in <module>
File "<string>", line 441, in <module>
File "<string>", line 264, in aes_encrypt_then_hmac
TypeError: str() takes at most 1 argument (2 given)
That is caused by the bytes
methods (1 - 2) in aes_encrypt_then_hmac
which is just an alias for str() in Python 2.7 and doesn't accept two arguments.
@hypnoticpattern We have spent some time trying to build either dual launchers or a single launcher to do both 2.7/3.x and the fundamental differences between the two languages have made it a non-trivial task. The way bytes are handled in Python 2 makes communicating with Empire problematic since we are moving to be solely Python 3.X for the server.
I think the ideal situation would be for us to be able to use 2.7 and 3 agents, and we are happy to include a pull request if you would like to develop this, but we would like to focus on updating some of the Powershell capability before tackling this problem, so it is not currently on our radar.
@Cx01N From an operator standpoint, the only place Python2 compatibility needs to be provided is in the agents. Since Python2 is EOL, I see no reason Empire should support it on the server side. An operator can always update their Empire server to the latest Python release, but Python2 agent compatibility would still matter for Linux/Unix or embedded devices that might still be running legacy Python2 only. I know going forward I will be running the Empire server using Python3 only.
@Invoke-Mimikatz I think we all agree that we would like to have both, it's just not at the top of the priorities.
Here's what we thought about when making this decision
Use of Python 2.7 isn’t recommended as this version is included in macOS for compatibility with legacy software. Future versions of macOS won’t include Python 2.7. Instead, it’s recommended that you run python3 from within Terminal.
So looking at the future, the python3 agent was more important to have. We'd love to have the 2.7 agents for older Linux machines and MacOS, but its just not at the top of our priorities. This is not a hard stance against support, we're just depending on those who need it to provide it at this time, and we are open to discussing how it could be implemented with anybody who wants to.
@Cx01N I can take a look and see if I can write a Python 2.7 agent that can talk to the Python 3 server. As you mentioned it won't be easy since the agent itself inherits pieces of code that are also used on the server side(e.g. crypto).
At the moment the MacOS stager is broken because the launcher uses the python 2.7 interpreter but is Python 3 code. Would be possible to update the application bundle and the launcher stagers to point to python3 (e.g. /usr/bin/python3)? I can work on that if you can point me to documentation on how the application bundle was developed.
@hypnoticpattern Unfortunately, we do not have a lot of documentation on how things were developed in the original Empire. The osx/application launcher is something that was preconfigured and is relatively foreign to us. @vinnybod tends to work on mac a lot more than the rest of us and he may be able to point you in the right direction.
I had a deeper look at project files and noticed macho.m
. That file should be the one used to create the Macho executable that is also included in the app bundle. Empire injects the Python code directly inside the __cstring
section of the compiled file replacing the hardcoded base64 string PAYLOAD.
macho.m
uses <Python/Python.h>
and that leverage the MacOS version of Python (i.e. 2.7.16). I wonder if there is a way to call python3 instead. For example the one shipped with XCode.
@hypnoticpattern Thanks! I've been checking it out and tried making some changes. It looks like it is leveraging the python files in /system/Library/Frameworks/Python.frameworks/Versions/2.7/. Since 3.7 isn't getting installed in this directory it is causing some issues. You can change the directory in the machotemplate to /usr/bin/python3 but you'll get that dylib isn't found. Hopefully, that helps.
@Cx01N The make it work the machotemplate needs Python3.framework shipped with XCode and it's in /Application/XCode.app/Contents/Developer/Library/Framework
.
At this point I see two options:
1) Use the .app bundle approach and include the Python3.framework there changing the linker option;
2) Use the Macho binary alone and change the dylib path to /Application/XCode.app/Contents/Developer/Library/Framework/Python3.framework
using install_name_tool
and "hope" XCode is installed.
@hypnoticpattern I am not sure which direction is the best, so I will leave it up to you since I rarely use osx as it is.
@hypnoticpattern Closing the issue for now. Please feel free to open a PR or new issue if you get the launcher updated.
Empire Version
3.0.5
OS Information (Linux flavor, Python version)
Server: Ubuntu 18.04.3 LTS (Bionic Beaver) |=> Python 3.6.9 Agent: Run on OSX Catalina 10.15.2 |=> Python 2.7.16 (the one used by the stager) |=> Python 2.7.17 (shipped with MacOS) |=> Python 3.7.3 (I manually installed it)
Expected behavior and description of the error, including any actions taken immediately prior to the error. The more detail the better.
After generating the stager for OSx and run the application bundle in MacOS the code doesn't do anything. To troubleshot the issue I run the binary within the app bundle and I get the following error:
I added a couple of lines within the launcherBase to verify what Python interpreter was used and I got this:
The reason of the error is because the launcher code was modified to be compatible with Python 2/3 (standard version) and the launcher moved from urllib2 (original Empire) to urllib (new version). The Python version used by the template in
Empire/data/misc/apptemplateResources/
is probably the Apple flavor and that doesn't have therequest
module in urllib:Is there a way to have a different Python version running with the templates in
Empire/data/misc/apptemplateResources/
?