Jump to content

C vs Rust vs Go for offensive security


Graham

Recommended Posts

I've recently decided to pick up a compiled language. I spent a while deciding if I should dive into C, Rust, or Go. Would love to hear your thoughts on what you would learn if you're coming from a pentesting background and have a firm grasp on python and bash.

 

I ended up jumping on the rust  bandwagon even though I'm fairly certain most people would recommend C to start out with. That being said, do you see rust and/or go becoming bigger in the future?

  • Like 1
Link to comment
Share on other sites

So, I'll preface this with saying "I haven't tried Rust or Go, so if that completely discounts what I'm about to say, fair enough" but from what I've heard from others, Rust is making a huge run for the top compiled language. That said, C having the legacy spot means most of the stuff you'll be debugging/reversing/poking holes in will be written in C for a while I'd imagine.

Open to being wrong, though. I'm looking at rewriting some of my C stuff in Rust later on.

  • Like 1
Link to comment
Share on other sites

3 minutes ago, valhalla_dev said:

So, I'll preface this with saying "I haven't tried Rust or Go, so if that completely discounts what I'm about to say, fair enough" but from what I've heard from others, Rust is making a huge run for the top compiled language. That said, C having the legacy spot means most of the stuff you'll be debugging/reversing/poking holes in will be written in C for a while I'd imagine.

Open to being wrong, though. I'm looking at rewriting some of my C stuff in Rust later on.

That is on par with what I have heard as well. From what I've gathered by annoyingly asking everyone I know this same question the answer seems to be "Learn C if you're looking at old software and learn rust if you're making new software". I wonder where Go falls in this category.

Link to comment
Share on other sites

I can't speak for Go, but in terms of Rust and C...

If I was writing any sort of tool I'd pick Rust. It's a much more modern language with useful things like growable vectors, sets, cross-platform networking and threads and so on in the standard library. The libraries available on crates.io are really easy to integrate if you want drop in support for handling, say, JSON or XML or any other formats.

If I was creating some sort of small shellcode it's probably easier to use C than Rust since I'm bound to be doing things with memory that Rust's compiler won't like. It's doable for sure but going against the grain.

One of Rust's strengths is that it's super pedantic about the difference between Strings (must always be perfect UTF-8), byte buffers, and filesystem path components and you have to jump through hoops to convert between these. If you're writing code where you have string-ish content but you want to twiddle particular ASCII bytes, you're quickly going to be trying to circumvent Rust's protections.

Meanwhile, if you're looking at anything decompiled/disassembled it would be helpful to think about what the original code could have been in terms of C, and the types of mistakes that could have been made.

  • Like 2
Link to comment
Share on other sites

I haven't really touched Go or rust yet but I've been learning C.

 

main reason why I chose C was because I was interested in malware analysis and exploit development.  I saw  @MalwareTech mention it in one of his blogs about languages needed for malware analysis.   I also saw it brought up numerous times as a prerequisite language needed for exploit dev on multiple blogs.

 

 

 

 

 

 

Link to comment
Share on other sites

I believe that all languages stated are necessary. 

Go could be a "replacement" for Python given it's super fast compile time, and easy to use syntax- plus GoLang gives you flexibility without having a runtime environment like Python uses.  Python however is more general purpose.  In most use cases I would use python PoC's and quick scripts, because it's kind of a standardized language that you don't need to know to understand the code written. Golang would be good for projects that require reuse, stability or speed but not scripts or likewise.  Another thing to note is GoLang compiled binaries can leak usernames and directories- so keep that in mind.

C  is everywhere, currently as it is, you must learn C if you want to do any reverse engineering etc.  You don't have to learn everything about C, but learning the basics and the little quirks it has goes a long way.  Most of the time C is still used today because a lot of code bases are already built with C; so why change?  There's a big up-spill in the Linux community about Rust's addition in the kernel.  I believe it will be a good addition, and many of the top contributors believe that Rust is easier to write in and work with, too; but a large amount of people dislike the change, mostly because they see it as a new "meta" language (from what I can see).  I personally find rust difficult to write in at times, but more enjoyable to any other language I have ever used.  A lot of that is due to the compiler, but also because I feel it forces me to write "proper", or "correct" code.  Rust is well known for it's memory safety, and I love that, but I also love the ecosystem around Rust (Cargo, Traits, Performance, and it's string manipulation etc)-.

As for the languages becoming bigger in the future, I think that Rust has more potential.  I think we will see Rust in more embedded systems and IoT devices. Whereas Go might take off in the web ecosystem, as it is a very strong language for backed API's and such, but it's hard to tell.

  • Like 2
Link to comment
Share on other sites

Go as offensive tooling requires you to think ahead of time about a lot of stuff. Like mentioned before, if not sanitized, it can accidentally leak information about the host it was compiled on. Its also not what you should choose if you're looking to make tiny implants. You're looking at multi-meg binaries in general, although done right you can sometimes get sub 1mb. 

 

What it is GREAT for is C2 clients. Because it cross compiles so easily (again, does require some thinking ahead on how to handle the differences between OS's), its easier to keep feature parity across clients. I also like using it for droppers, because of how nice to use the native embed package. You can also still call c and native windows functions, and I've implemented loaders that can load processes in memory in a variety of ways. 

 

From the defensive side, golang bins that have been properly sanitized can be an absolute nightmare to try to RE, mainly due to its runtime as well as the way it handles string and byte data. 

  • Like 1
Link to comment
Share on other sites

I think it's best to use the language you're most comfortable with, I tested C, C++, rust, and nim and for my part, I have a small preference for C++ and potentially nim

Link to comment
Share on other sites

While I really like Rust it wouldn't be my first choice when learning a compiled language for offensive security purposes. You are probably going to want to use Windows API frequently and because Rust handles strings in UTF-8 and Windows API requires string in ANSI or UTF-16 you'll have to do conversion. It's not that hard to get used to it, but it can lead to frustration that you're not making any progress when starting.

Try to do something simple in all three and see what you like best.

Link to comment
Share on other sites

Pretty alright at both C and Rust, not touched Go. But if you want my opinion; Rust for any modern tools and programs. Once you get past the initial learning curve and borrow checking, it’s a joy to use. The compiler is incredibly handy, and albeit a little slow - the program runs very efficiently and fast though. Haven’t touched C/C++ since.

Link to comment
Share on other sites

I'm been programming with c for a very long time. Go seems like an good language, it's able to compile to native so it's runs just as fast as C but it's comes out as a massive size and it's Google. As for Rust, I really don't know. The code looks complicated when it should be easy which is a problem in C++ and you still have unsafe command that is still used.

There is a research search that did a study on Rust programs and the use of keyword of unsafe and they found out that unsafe was still used in professional Rust programs and can cause exploits to happen, so...

I also read an very long blog post on Apple's kmalloc (https://security.apple.com/blog/towards-the-next-generation-of-xnu-memory-safety/). They explain a new attempt to get rid of use after free exploit for good. Hopefully, there will be more improvements to get rid of memory exploits so using C or C++ won't be not longer be a problem.

Link to comment
Share on other sites

Depends on what you're doing and what you're targeting.

FWIW, C is going to be available on absolutely every architecture you might ever want to touch, and it's exactly the sort of language that allows easy access to "doing really inadvisable things to systems"

Rust, OTOH, definitely keeps a lot of that silly stuff away from you [unless you go into unsafe blocks, where you can then pull shenanigans - but that's something that gets introduced comparatively late]

C binaries are going to be smaller than Rust ones in almost all cases; speed will depend on how much optimization you want to do on either; Rust is, at -present-, a little harder to RE because there's not as much tooling out there to do that.

Rust has, IMO, a much nicer toolchain than C - the whole cargo ecosystem allows for rapid development and lets you get to "actually doing things" rather than "writing out fucking boilerplate again"

The -hard- part about Rust is that you absolutely need to fully understand what you are going to do with the program before you write it.

[ Yes, I left golang out. I dislike it and don't use it. ]

  • Like 2
Link to comment
Share on other sites

On 11/6/2022 at 12:53 AM, habitual said:

Go as offensive tooling requires you to think ahead of time about a lot of stuff. Like mentioned before, if not sanitized, it can accidentally leak information about the host it was compiled on. Its also not what you should choose if you're looking to make tiny implants. You're looking at multi-meg binaries in general, although done right you can sometimes get sub 1mb. 

 

What it is GREAT for is C2 clients. Because it cross compiles so easily (again, does require some thinking ahead on how to handle the differences between OS's), its easier to keep feature parity across clients. I also like using it for droppers, because of how nice to use the native embed package. You can also still call c and native windows functions, and I've implemented loaders that can load processes in memory in a variety of ways. 

 

From the defensive side, golang bins that have been properly sanitized can be an absolute nightmare to try to RE, mainly due to its runtime as well as the way it handles string and byte data. 

What methods/tools do you use to obfuscate Go binaries?

Link to comment
Share on other sites

23 hours ago, gnugro said:

What methods/tools do you use to obfuscate Go binaries?

Would love to know more about this; stripping the binary and using code coverage tools just feels like the start.

Link to comment
Share on other sites

Started learning Go recently as my first compiled language and have been enjoying it. Definitely made me curious about C and Rust but feel that staying focused on Go for the meantime is best for my situation.

Not very strong in other languages so I think Go was a good choice. Interested to hear if anyone has suggestions/thoughts. Some resources in case anyone has similar circumstances to me:

https://quii.gitbook.io/learn-go-with-tests/

https://gophercises.com/

https://exercism.org/tracks/go

On 11/7/2022 at 12:39 AM, j91321 said:

While I really like Rust it wouldn't be my first choice when learning a compiled language for offensive security purposes. You are probably going to want to use Windows API frequently and because Rust handles strings in UTF-8 and Windows API requires string in ANSI or UTF-16 you'll have to do conversion. It's not that hard to get used to it, but it can lead to frustration that you're not making any progress when starting.

Try to do something simple in all three and see what you like best.

I think j91321's suggestion is best though

  • Like 1
Link to comment
Share on other sites

On 11/9/2022 at 8:18 PM, gnugro said:

What methods/tools do you use to obfuscate Go binaries?

Couple different things I like to do. One option is garble, which wraps the go toolchain and replaces and removes a lot of stuff. Downside is it sometimes gets picked up by AV because of how distinct it looks.  

https://github.com/burrowers/garble

 

goobfuscate does something similar, except it just makes a copy of your source and obfuscates some stuff. Less in depth,  but the upside is that its less distinct than garble.  

https://github.com/unixpickle/gobfuscate

 

 Most of the time I prefer to UPX pack it, then break the UPX headers so that it needs to be patched to be unpacked, but not ran.

  • Thanks 1
Link to comment
Share on other sites

2 hours ago, habitual said:

Couple different things I like to do. One option is garble, which wraps the go toolchain and replaces and removes a lot of stuff. Downside is it sometimes gets picked up by AV because of how distinct it looks.  

https://github.com/burrowers/garble

 

goobfuscate does something similar, except it just makes a copy of your source and obfuscates some stuff. Less in depth,  but the upside is that its less distinct than garble.  

https://github.com/unixpickle/gobfuscate

 

 Most of the time I prefer to UPX pack it, then break the UPX headers so that it needs to be patched to be unpacked, but not ran.

I like the idea of breaking the UPX header.  I usually use UPX, though I didn't think to use that strategy.  I can look at that for other packers, as well.  I appreciate it!

Link to comment
Share on other sites

So I have coded in c++ and c#(if c# counts in this topic) but I had the same dilemma. Rust or Go?

I had good Dev friend of mine, who touched both and C/C++/C#, told me that "V" is pretty nice. So I tried It in my free time and still code with it when I have the time. I like it, it's like 90% Go as far as syntax goes. It is pretty new so for problems I encounter I search it on Go forums. It's cross platform for like every thing compiles as fast as C and is like pretty security oriented.

So, if you can't make the choice go "v"

Edited by lurto
Link to comment
Share on other sites

On 11/11/2022 at 11:36 AM, gnugro said:

I like the idea of breaking the UPX header.  I usually use UPX, though I didn't think to use that strategy.  I can look at that for other packers, as well.  I appreciate it!

One really fun thing to do is add in a self check into the malware so that it looks at its own headers and checks to see if the UPX break is still there, and only runs if the binary has not been patched or unpacked. Really messes with automated dynamic analysis. 

Link to comment
Share on other sites

7 hours ago, habitual said:

One really fun thing to do is add in a self check into the malware so that it looks at its own headers and checks to see if the UPX break is still there, and only runs if the binary has not been patched or unpacked. Really messes with automated dynamic analysis. 

Oh yes.  That is clever.  Thanks for that tip.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...