Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it actual sniffer and support encryption. #1

Closed
MajsterTynek opened this issue Nov 17, 2020 · 16 comments
Closed

Make it actual sniffer and support encryption. #1

MajsterTynek opened this issue Nov 17, 2020 · 16 comments

Comments

@MajsterTynek
Copy link

Move from proxying to sniffing is optional here.
When encryption is requested, we may still listen to packet talk,
but not interfere with communication happening after that.

We may breach encryption by making the client share it's shared secret.
I have made a Lua script that logs it to a file for further use.
I have already tested this solution by dumping TCP streams
and decrypting them with said logged key.

I suggested this somewhere else already:
uis246/MCPC_dissect#2

All SniffCraft has to do on encryption request is to start
listening to that file for key and match proxy connection
by identifying local(Client) and remote(Proxy) addresses
and their ports. (Not server's IP+port we proxy to.)

BTW For connecting beside the local machine,
the proxy should always patch Handshake packet to
proper values to not include local IP and port.

BTW2 I might implement that script for other MC versions if needed.
You can contact me on Discord under username MajsterTynek#8884
or find me on AdvancedMacros Discord server.

@adepierre
Copy link
Owner

Actually I've already considered the sniffing option over proxy. And I've selected proxying because of two problems with packet sniffing:

  • TCP packets might come in a different order than the stream and out of order packets then have to be dealt with using sequence numbers. It's an additional layer that has to be added to the code.
  • sniffing might have some missing packets. In case of high network usage, sniffing is not reliable and packets can be dumped before they are captured.

For the encryption I didn't know the existence of any Lua script capability in minecraft. Is this a mod? But it should in theory be a solution, at the cost of asking people to add at least this script to their client. Could you give me more information on this Lua thing? I'll see if I can find some time to dig more in this direction.

And good catch for the handshake packet, I'll fix this.

@MajsterTynek
Copy link
Author

I use this mod because besides exposed Lua stuff
it allows interaction with Java classes thus Minecraft internals.
When allowPrivateAccess is enabled, it allows for a violation of Java modifiers,
so I could grab key value by reaching the Cipher instance from the pipeline.

However, I believe it is possible to
implement it as a separate mod using Mixins,
but I am not a Java developer to judge that.

Here is a link to the mod on CurseForge where releases are hosted:
https://www.curseforge.com/minecraft/mc-mods/advanced-macros
and message on Discord where I have originally posted the script:
https://discord.com/channels/473440074047160331/707597339979808859/742411766843047937

I have posted and explained usage here:
uis246/MCPC_dissect#2 (comment)
You may need this one: Tutorial on how to bind scripts:
https://advancedmacros.github.io/docs/quickstart/
You don't need to use internal editor, just create file externally:
.minecraft\mods\advancedMacros\macros\shared_secret.lua

inb4: How to enable private access for LuaJ
Type this line by line in REPL (under left ALT+L)
getSettings().luajava = getSettings().luajava or {}
getSettings().luajava.allowPrivateAccess = true
getSettings().save()
Then restart The Game.

If you have any more questions about the Mod,
feel free to join our Discord server, which I am part of.

@adepierre
Copy link
Owner

I've fixed the potential issue with the Handshake packet.

I've also decided I wouldn't implement the encryption support using a client modification. If a client mod is needed for it to work then you might as well directly get the packets from the client and avoid the hassle of using SniffCraft in the first place.

@MajsterTynek
Copy link
Author

@adepierre any hints on how could I bring encryption to SniffCraft in my own build knowing encryption keys?
I am not enough experienced in the usage of BotCraft library to get it working by myself.

@adepierre
Copy link
Owner

adepierre commented Dec 10, 2020

You should look at the AESEncrypter class in Botcraft .

It's responsible to encrypt outgoing packets here and decrypt incoming packets here.

You should check how it is initialized in Botcraft and try to mirror it in SniffCraft using the shared secret you got.

@uis246
Copy link

uis246 commented Jul 6, 2021

  • TCP packets might come in a different order than the stream and out of order packets then have to be dealt with using sequence numbers. It's an additional layer that has to be added to the code.

Wireshark developers already done all work.
https://github.com/uis246/MCPC_dissect/blob/master/mcpc.c#L260
tcp_dissect_pdus do packet reassembling. It's simple :)

  • sniffing might have some missing packets. In case of high network usage, sniffing is not reliable and packets can be dumped before they are captured.

Err... What? Maybe probloblems with translation.
Dumped before captured? What do you mean? I don't understand.
And missing packets are missing for client too.

@adepierre
Copy link
Owner

adepierre commented Jul 6, 2021

Wireshark developers already done all work

Yep, I know it's possible, I've done it for another project. But pointless in this case as the proxy approach is used.

Err... What? Maybe probloblems with translation.

Nope, no probloblems here. I've already seen situations in which an application actually received some packets that wireshark didn't capture at all.
More details directly from the tcpdump page:

packets "dropped by kernel'' is the number of packets that were dropped, due to a lack of buffer space, by the packet capture mechanism in the OS on which tcpdump is running, if the OS reports that information to applications; if not, it will be reported as 0

@uis246
Copy link

uis246 commented Jul 6, 2021

Nope, no probloblems here.

Ouch. Mistyped. But at least now I know how to name problems with blobs - probloblems.

@uis246
Copy link

uis246 commented Jul 6, 2021

More details directly from the tcpdump page:

packets "dropped by kernel'' is the number of packets that were dropped, due to a lack of buffer space, by the packet capture mechanism in the OS on which tcpdump is running, if the OS reports that information to applications; if not, it will be reported as 0

Thanks

@MajsterTynek
Copy link
Author

@uis246 @adepierre
I am working on a mod for collecting encryption keys,
so no sketchy script will be needed anymore;
I could even move the encryption layer onto a proxy,
so the proxy could do it itself with a clear view of passing data.
https://github.com/MajsterTynek/NotSoSecret

@uis246
Copy link

uis246 commented Jul 8, 2021

I could even move the encryption layer onto a proxy

Not the best design choice

@MajsterTynek
Copy link
Author

I could even move the encryption layer onto a proxy

Not the best design choice

I meant it for local connections,
just for debug and testing purposes.
Everything will be a toggleable setting.

@MajsterTynek
Copy link
Author

@adepierre any updates about proxying with encryption? or is it still open case?

@adepierre
Copy link
Owner

@adepierre any updates about proxying with encryption? or is it still open case?

It's actually supported since september 2021 😀

See this part of the readme for more info.

@MajsterTynek
Copy link
Author

Microsoft Authentication

@adepierre Any hints how to wrap around MS authentification?
I have seen article on wiki.vg, but I cannot fully grasp it. ;/

authentifier = std::make_unique<Botcraft::Authentifier>();
const std::string credentials_cache_key = json.contains("MicrosoftAccountCacheKey") ? json["MicrosoftAccountCacheKey"].get<std::string>() : "";
std::cout << "Trying to authenticate using Microsoft account" << std::endl;
if (!authentifier->AuthMicrosoft(credentials_cache_key))
{
std::cerr << "Error trying to authenticate with Microsoft account" << std::endl;
throw std::runtime_error("Error trying to authenticate with Microsoft account");
}

I have spotted this very code piece above which uses MicrosoftAccountCacheKey from settings file.
How does one get keys from several Microsoft accounts and auths with them?
Last time when reading wiki.vg article I have got scared away by requrement of "creating a Microsoft Azure application".
Have you done somewhat differently or it is as proposed by wiki.vg article? D:
inb4 I have found a spare Azure ID from one of your issues. ;)

Offtopic

Just remembered about this issue I wrote long time ago here.
You quite implemented the very thing I kept only as ideas. :O

Encryption done in assembly

Recently I am tinkering with x86_64 assembly and I have almost implemented
in-place encryption/decryption with AES-AES-NI and SSE4.1 instructions.
I intend to use it for my self-contained headless Lua scripting client. Function declarations:

#define AESNI_ENCRYPT 1 // mode choice
#define AESNI_DECRYPT 0 // mode choice
#define cfb8_crypt(k,v,i,s,m) \
    (m?cfb8_encrypt:cfb8_decrypt)(k,v,i,s)

/// in-place encryption function typedef
typedef void* CRYPT_FUN(void*,void*,void*,size_t);

/// creates 10 round keys from a key
void cfb8_key(void* _keys, void* _key);

/// cipher functions for AES-128-CFB8
CRYPT_FUN cfb8_encrypt, cfb8_decrypt;

Would any of this have an use here in proxy domain?
What's the efficiency of current implementation
in SniffCraft and whether does it matter?

@adepierre
Copy link
Owner

Regarding Microsoft Auth, I basically created one dummy azure application and got the ID and never touched the app since. Hope it'll stay alive somewhere in Microsoft world.

There are two ways of authenticating using this ID. First way is traditional oauth stuff with HTTP server and redirections. The second way is device flow authentication for which you basically give a code to the user. This code can be used to authenticate on any browser (externally from the app). In the meantime, the app pings a Microsoft server endpoint using the given code and the server responds with "nope, the user is not logged in yet" or "all good, user authenticated here is your token".

Regarding the efficiency of the current encryption/decryption methods, I never really try to benchmark/optimize openssl functions but it never appeared as a bottleneck so I prefer keeping it working rather than touching and risking breaking it. I'm not very familiar with these cryptographic topics so I just use what's available and working for me.

Btw if you want to discuss more you could join the discord server, it's on the readme, it could be easier to exchange than github issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants