jfjallid / go-smb

A client library to interact with Windows RPC services such as MS-SRVS and MS-RRP.
MIT License
40 stars 9 forks source link

[Discussion] Compile with garble #9

Closed XiaoliChan closed 5 months ago

XiaoliChan commented 5 months ago

In most use cases of go-smb (like go-secdump, go-shareenum) is always be a landing file(binary) into the comprised target, so the good solution of bypassAV with golang binary is compile with garble.

I have tried to compile with garble, but it got unexpected with NetShareEnumAll function

[+] Signing is NOT required
[+] Login successful
Cannot find field name within struct: Path

I think something wrong with the function getOffsetByFieldName after obfuscated with garble

Reference:

jfjallid commented 5 months ago

Tools like go-secdump and go-shareenum are designed to be run remotely against a target rather than targeting localhost, so typically there is no EDR/AV running on the machine executing the go-secdump or go-shareenum binaries to hide from. This library supports running connections through a SOCKS proxy so I would probably never run those tools on a machine where I need to avoid detection for the go binaries.

I haven't looked at garble before but from a quick overview it looks like obfuscating Go types might break Reflection which is heavily used by the SMB encoder component of which getOffsetByFieldName is a part of.

XiaoliChan commented 5 months ago

Tools like go-secdump and go-shareenum are designed to be run remotely against a target rather than targeting localhost, so typically there is no EDR/AV running on the machine executing the go-secdump or go-shareenum binaries to hide from. This library supports running connections through a SOCKS proxy so I would probably never run those tools on a machine where I need to avoid detection for the go binaries.

Haha, interesting, I always think this is landing on the comprised target. And the reason why I said "landing", because I make a go version crackmapexec with your library, and I always make it land into the comprised target (network scanner always working better than through proxy)

I haven't looked at garble before but from a quick overview it looks like obfuscating Go types might break Reflection which is heavily used by the SMB encoder component of which getOffsetByFieldName is a part of.

Yes, garble with break the reflection, but I have no idea how to fix it.

jfjallid commented 5 months ago

With tools such as Nmap I can agree that they work better without a proxy to minimize delay and jitter, but take go-secdump as an example. It is designed to communicate with Windows Remote Registry to retrieve secrets without having to touch disk on the target system. So while it could be executed on one compromised machine to target another in the same network, it works as well to run from a an "attacker" host with network access towards the target. I see no reason to run go-secdump to retrieve secrets from localhost.

However, if you have to bring your toolbox to a system with an EDR and execute the tools from there I can understand the problem. In most situations I'd expect the user of go-smb to either have network access to the targets from their own machine where they can run the tools without handling an EDR, or to have access to a C2 framework such as Cobalt Strike in which case they could tunnel the SMB traffic through a SOCKS proxy.

The SMB encoder/decoder component of go-smb is quite complex and I've started to move away from it to instead implement custom encoders/decoders. A long-term solution could be to move away from it entirely in which case garble would likely work better since at least the problem with Reflection would go away.

Moving away from the dynamic encoder/decoder is not a main priority for me though so if you want it done or if you figure out some other way to solve the Garble problem such as adding what that library refers to as hints I'm open to Pull Requests.

XiaoliChan commented 5 months ago

@jfjallid A bug I found

github.com/jfjallid/go-smb/smb.(*Connection).NegotiateProtocol(0xc001120000)                                                                                                                               
        github.com/jfjallid/go-smb@v0.3.4/smb/session.go:185 +0x1ba5                                                                                                                                       
github.com/jfjallid/go-smb/smb.NewConnection({{0xc0004fc030, 0xc}, 0x1bd, {0x0, 0x0}, {0x0, 0x0}, {0x0, 0x0}, {0x0, ...}, ...})                                                                            
        github.com/jfjallid/go-smb@v0.3.4/smb/connection.go:368 +0x73d                                                                                                                                     
main/Plugins.SMBv2_NTLMInfo(0xc0006943c0)                                                                                                                                                            
        main/Plugins/smb.go:123 +0x158
main/Plugins.SMBScan(0x1?)                                                                                                                                                                           
        main/Plugins/smb.go:26 +0x78                                                           
reflect.Value.call({0xfbc380?, 0x1432e90?, 0x13?}, {0x1164e94, 0x4}, {0xc001104f78, 0x1, 0x1?})      
        reflect/value.go:586 +0xb07                                                                                                                                                                        
reflect.Value.Call({0xfbc380?, 0x1432e90?, 0xc0004fc03d?}, {0xc000c62778?, 0xc000c627b8?, 0x1?})                                                                                                           
        reflect/value.go:370 +0xbc                                                                                                                                                                         
main/Plugins.ScanFunc(0x43f705?, 0xc0006943c0)                                                                                                                                                       
        main/Plugins/scanner.go:160 +0x196                                                                                                                                                           
main/Plugins.AddScan.func1()                                                                                                                                                                         
        main/Plugins/scanner.go:148 +0xb7  
created by main/Plugins.AddScan
        main/Plugins/scanner.go:144 +0x18c

Easy to reproduce, just run a smb server with impacket's smbserver.py with command sudo smbserver.py a $(pwd) -username a -password a -smb2support

Version 0.3.2 has no issues

jfjallid commented 5 months ago

Thanks for the report, but please open a new issue for it so it can be tracked separately.