Welcome, Guest
Welcome to Makestation! We are a creative arts/indie discussion community — Your center for creative arts discussion, unleashed!

Please note that you must log in to participate in discussions on the forum. If you do not have an account, you can create one here. We hope you enjoy the forum!

Status Updates
Avatar of User
tc4me January 6th, 2025
the forum is being flooded with spammers!
Avatar of User
tc4me January 6th, 2025
the forum is being flooded with spammers!
Avatar of User
tc4me January 6th, 2025
the forum is being flooded with spammers!
Avatar of User
tc4me January 6th, 2025
the forum is being flooded with spammers!
Avatar of User
tc4me January 6th, 2025
the forum is being flooded with spammers!
View all updates

Search Forums

(Advanced Search)

Forum Statistics
» Members: 1,012
» Latest member: shayjohnson9112
» Forum threads: 7,017
» Forum posts: 31,292

Full Statistics

Online Users
There are currently 395 online users.
» 1 Member(s) | 393 Guest(s)
Google, HamuBh

Latest Threads
Exclusive Temu Coupon [ac...
Forum: Simmania
Last Post: HamuBh
1 minute ago
» Replies: 0
» Views: 1
[New] Temu Coupon Code $1...
Forum: Announcements
Last Post: HamuBh
5 minutes ago
» Replies: 0
» Views: 1
Verified Temu Coupon Code...
Forum: General Discussion
Last Post: Mr.PrinceApe
32 minutes ago
» Replies: 0
» Views: 7
Temu Promo Code [acs67088...
Forum: Announcements
Last Post: granny24
40 minutes ago
» Replies: 0
» Views: 3
30% Off Temu Coupon Code ...
Forum: Announcements
Last Post: granny24
42 minutes ago
» Replies: 0
» Views: 3
Temu Coupon Code 90% Off ...
Forum: Announcements
Last Post: granny24
47 minutes ago
» Replies: 0
» Views: 3
Temu Coupon Code $200 Off...
Forum: Announcements
Last Post: granny24
52 minutes ago
» Replies: 0
» Views: 3

 
  Hello
Posted by: NealCaffrey - December 22nd, 2019 at 6:17 PM - Forum: Introductions - Replies (3)

Hello my name is NealCaffrey. 
Found this forum because a friend of mine told me about it.

Print this item

  This Land is My Land
Posted by: Guardian - November 28th, 2019 at 4:50 PM - Forum: Other Games - Replies (8)

So, I bought this early access game on Steam, and I can't stop playing it. It's still got bugs, and still needs some work, but its already a masterpiece:

Quote:Experience the frontier as a chief of a Native American tribe and resist the onset of the settlers. Explore the vast world full of hostile humans and animals while defining your narrative through the decisions you make. Survive, hunt, craft, unite and lead the tribes to take back your lands. 

Steam page: https://store.steampowered.com/app/10696...s_My_Land/

Every playthrough is different, as the game world is procedurally generated and even the name you choose comes with different benefits or struggles.

Print this item

  Dev Software
Posted by: Lain - November 7th, 2019 at 3:59 PM - Forum: Software - Replies (8)

I'm considering wiping my PC yet again and I can usually get down my 'essential' software within a few minutes. After that, I focus on getting all my dev shit down and sorted nicely.

So what are your usual editors/toolchains/IDEs that you install whenever building back up?

Windows:
Text Editor:

  • VS Code
  • EmEditor
IDE(s):
  • CLion (C/C++)
  • GoLand (Go)
  • IntelliJ (Java)
  • Visual Studio (.Net, some C/C++ related stuff too.)
  • Arduino (Arduino)
  • Keil uVision (microvision) (Embedded applications in C, MDK)
  • Gnat/GPS (Ada)
Other:
  • STM32cubeMX (Code generator for STM32 boards)
  • Fritzing (Schematics)
  • Choco/NuGet (Package Managers)
  • Git
Toolchains:
  • Node
  • MinGW (C/C++)
  • Non-VB/C# VisualStudio packages (F#, linux, etc.)

Linux:
Text Editors:
  • VS Code
  • nvim
  • Atom (ONLY if VS Code isn't supported on the target without overlays, AKA Gentoo)
IDEs:
  • Arduino
  • mBed (not installed, just what I use.)
Other:
  • Git
Toolchains:
  • Node
  • GCC family
Most of my Linux development is in C so I don't need to go overboard with the IDEs (not that there are many good ones available for Linux.)

Print this item

  NandGame
Posted by: Lain - November 5th, 2019 at 3:46 AM - Forum: Technology & Hardware - Replies (8)

I found a cool game a while ago in some /g/ thread about building a CPU straight from scratch called NandGame.
Link: http://nandgame.com/

You might have learned about some of this stuff in a uni-level computer architecture course, and probably know about lots of the actual gates from either programming or high-school level logic/engineering classes. In any case, the game's pretty fun, I'm currently on the memory section trying to figure out the flip flop (even though I'm familiar with the concept already).

It focuses a lot on NAND (not-and, or inv-and) because, realistically, NAND gates are the cheapest (and sometimes the smallest) to make in fact, that in modern CPU architectures primarily just use NAND gates to build other logic systems. As such, it's theoretically possible to build everything in-game with just NAND gates.

But that would just clutter your screen, so you can use parts that you've already made to build other parts, until you start working your way up to more complex parts where you might be only given your primitive logic gates to complete a level, and in those cases, I've found myself just building those solutions with NAND/NOT gates.

Give it a shot, it's pretty fun and you'll learn lots about how computers work at a hardware level.

Print this item

  Bit Fields for Dummies
Posted by: Lain - November 4th, 2019 at 11:04 PM - Forum: Software - No Replies

I recently completed an online course on embedded applications using C.
To tell you the truth, it wasn't worth the few hours I invested in it. I more or less scanned through all the material, and most of it was intro stuff I already knew about optimization, like bit masking using logical/bitwise operators, compiler optimizations, const vs. #define, etc. Nothing particularly difficult to understand as long as you have a good foundation in computer science, ie. understanding how a CPU actually works.

But there was one thing that I did learn, and have wondered about before.

Take some data structure for example. Using C pseudocode, we can assume something that looks like this:

Code:
struct {
    //some code
}myBools;

And inside that data structure, you've got a bunch of boolean values (ie. true/false)

Code:
struct {
    bool var1;
    bool var2;

    bool var3;
    bool var4;
    bool var5;
    bool var6;
    bool var7;
    bool var8;
}myBools;

Well, note how in this specific use-case, I have eight values in this one structure. Now, Boolean values are either 0 or 1 traditionally, so how large is this data structure?
Well, 0/1 imply bits, so you might think 8 bits, or one byte.
Wrong.
In C, by default, a boolean value takes up one byte minimum, and since most other primitive data types (ie. int, double/float, char, etc.) can also be larger than one byte, we can say that the size can be much greater.

So the data structure given above isn't one byte, but it's eight bytes.

Now, this distresses me. If they're bools, they should only technically be 0 or 1 (or 0 and not 0) so we should be able to cut program size costs from an extra eight bytes to a single byte if we were to modify/read individual bit values.

And sure enough, you can mask/read/write bit values pretty easily, if you used a macro function like this:
Code:
#define MASK(x) (1<<x)

int main(){

    const char toRead = 0b01001100; //Some 1 byte value defined in binary
    uint_8 readVal; //Whatever the value of what we read will be, one byte in size

    //read a single byte from a character value
    readVal = (toRead >> 3) & MASK(3);
    //returns 1

    //toggle a single bit:
    toRead ^= MASK(3);
    //returns 0b01000100

    //to set a bit (back)
    toRead |= MASK(3);
    //returns back to 0b01001100
    return 0;
}

But as you can see, using macro functions everywhere can start to make things really unclear, especially when you start to combine them.

Instead, in this course, they covered a cool concept called a 'bit field' which does exactly this, but without the messy code.

Let's go back to our first struct of bools. Instead, we'll rewrite it:

Code:
struct {
    uint_8 var1 : 1;
    uint_8 var2 : 1;
    uint_8 var3 : 1;
    uint_8 var4 : 1;
    uint_8 var5 : 1;
    uint_8 var6 : 1;
    uint_8 var7 : 1;
    uint_8 var8 : 1;
}myBools;

So the format is slightly familiar yet still different. 
Code:
type Name : bitSize;

Realistically, any type can be used here, but I'm using single-byte ints for the sake of looking cool. What's important is the colon and size of the value in bits. Yes, you can have more than one, say three bits, and so when that field is read, you may have a value from 0-7 (or a three-bit value, 2^3)

Now, we can take another step further. What if you want to set/read a single bit rather than a specified group that you already made in the struct?
Well, you mush them all together. To do that, we use a union (or a structure that is split up and shares memory.)

Code:
union{
    uint_8 full;
    struct{
        uint_8 bit0 : 1;
        uint_8 bit1 : 1;
        uint_8 bit2 : 1;
        uint_8 bit3 : 1;
        uint_8 bit4 : 1;
        uint_8 bit5 : 1;
        uint_8 bit6 : 1;
        uint_8 bit7 : 1;
    }bits;

    struct{
        uint_8 bit0 : 3;
        uint_8 bit1 : 2;
        uint_8 bit2 : 1;
        uint_8 bit3 : 1;
        uint_8 bit4 : 1;
    }fields;
}bitField;

//Examples
int main(){
    bitField a = 0b01001100; //Same number as above.
    uint_8 readVal;

    //To read a single byte
    readVal = a.bits.bit3;
    //returns 1

    //To read the first three bits in the field:
    readVal = a.fields.bit0;
    //Returns 4

    //To set a bit:
    a.bits.bit3 = 0;
    
    //To toggle a bit:
    a.bits.bit3 ^= 1;

    //To read the value of the whole byte:
    readVal = a.full;
    //returns 0b01001100, or 76, or 0x4C

    return 0;
}

So in short, that's how you turn a structure of eight bytes into a structure of eight bits instead, without making the code completely unreadable.

It feels a little more object oriented this way, but overall, it's pretty well optimized.

Print this item

  A little more RE
Posted by: Lain - October 25th, 2019 at 7:33 PM - Forum: Software - Replies (4)

I've been holding onto a file for almost a decade now. To be exact, very late 2010, maybe early 2011. We're soon approaching a full nine years, and I've been holding onto this file essentially since I was a dumb kid in the hopes that one day I'll be able to do something with it.

The file doesn't even technically work. It's a trainer for Call of Duty: Black Ops which was made shortly after the game came out (only allegedly worked for Campaign/Solo zombies) and was shortly patched thereafter. Sure, it looked sort of cool, design-wise:
[Image: 1f0f862259d53fadca7c9eb0b674aaa8.png]

But otherwise, it was patched, and thus, did not even work.
I kept this file throughout the years for one reason alone: to figure out how to extract the music file.

I cannot find this version of the song anywhere online, since lots of demoscene music generally is pretty obscure (think of late 90s/early 00s chiptune in trainers/keygens) and even the song itself is relatively obscure: The NeverEnding Story by Limahl (the theme to the movie.)

So over the years, as I'd learn more about programming or general computer science, I'd think of ways that maybe I could use something to help me figure out how to take this program apart, and hopefully something will finally make the dent I needed.

Now, LinGon is long gone, can't find any new handle and his social media/old accounts haven't been touched since like 2013 at latest. So asking him for help would have been out of the question.

The file in question is here, for anyone's will to follow along with the process:

Code:
[url=http://www.mediafire.com/file/1yhgkz6u7r61c4c/CODBO%252B11Trainer-LinGon.exe/file]http://www.mediafire.com/file/1yhgkz6u7r61c4c/CODBO%252B11Trainer-LinGon.exe/file[/url]

Before you ever run a program on your computer, especially something that can be considered a hack tool, you should scan it with VirusTotal or something. For me, as a hobbyist, I've found that tons of samples will come back infected despite being clean because of strange function calls, and that it's also incredibly easy to make a sample that doesn't get detected. Weird world, so instead of trusting the results of a bunch of AVs, I use HybridAnalysis to get clues about what the program does, then I make the decision of actually running/debugging the program myself.

At the time of playing CoD:BO, I was running Windows 7 in those days, and I only had 4GB of RAM so I figured using the 32bit options on HA would be fine to test. After all, I'm not looking for detections, I'm looking for clues.
[Image: ec81fcfd874435088221e4f95a624917.png]

Unfortunately, HA thinks the file is malicious:
https://www.hybrid-analysis.com/sample/7...8042042fcc

Why?
Because allegedly it reads 'terminal service related keys'
And apparently RDP programs do that.
You know what else does that?
Trainers (and game-hacking tools.)
Why?
Because you need to get around anticheat somehow, buddy.

This was the only mainly concerning aspect of the analysis done, and it's easily explained. There's no web-traffic or any networking whatsoever (it doesn't even import the necessary networking libraries) so it's unlikely anything malicious is going on. 

There were a few things that stood out to me from the analysis though:
Code:
Written/Compiled with VisualBasic 6.0
Packed with PECompact
Barely any discernable strings (reinforces the packed idea)
Strange API imports (likely due to the packing)
No files extracted

VisualBasic means that maybe we can do some dotnet RE which would make life easier.
PECompact gives us at least the name of what we're looking for when we want to unpack it.
No files means that the resources section of the file is also packed. I was hoping to maybe get an MP3 from this, but I suppose not.

Since it's allegedly written in VB6, we should try to decompile to VB6 (even if it's undiscernable initially,) so I plugged the file into dotPeek, a free .Net decompiler. It works on .exes, .dlls, or any binary for that matter as long as it's written in a .NET language, like VB.
[Image: 0bc1d942a3874607eceb361ca308977f.png]
No go.
Guess not.

So now, we need to bring out the big guns. A real debugger, since although it's importing all the .Net stuff, it's hidden so there's probably lots of native code surrounding it.
Enter x64dbg (or x32dbg in my case.)

x64dbg (known as xdbg from here-on-in) is essentially the spiritual successor to the world-famous OllyDBG, except that Olly has way less features and doesn't work for 64bit binaries, making it a little too useless in the modern-day. xdbg also supports 32bit binaries, and is entirely free, making it a great choice for us right now.

So I downloaded the binaries, started up x32dbg (the 32bit version obviously,) and plugged in the Trainer file I've been saving for today.
[Image: db463ba19d642e76d94d979a194cc42a.png]
And it seems to work fine. It hits a system breakpoint and stops execution, allowing me to start poking around.
First, to understand most packing schemes, there's very little you need to know. Most packing/obfuscation schemes operate sort of similar to this pseudo-ASM code:

Code:
0x401000 ---- jmp 0x601000 ;entry point of the binary, jumps to arbitrary location, assume this instruction is 5 bytes
0x401005 ---- ;garbled nonsense spanning the majority of the file
....
....
0x601000 ---- call decryptGarbled ;decryption function for the above garbled mess
0x601004 ---- add ebp,5 ;adjust execution stack pointer by 5 bytes, ie. makes 0x401000 into 0x401005, changing the base
0x601010 ---- jmp [0x0] ;starts execution from where the garbled was, now decrypted code.

So realistically, we just need to follow the trail.
First, in xdbg, we need to find that entry point for the program (currently the breakpoint is highlighted, also in a different section than the program itself, so we need to poke around more. The logs show us something interesting:
[Image: 40a9a0a007799c1f3232ee8355967e20.png]

And there it is, also neatly hyperlinked for our convenience!
Clicking it starts off our journey:
[Image: 50638429cf8b9831728a73218a813a06.png]

And just our luck, there's a new address being pushed into the accumulator.
First, I'll assemble that one instruction and note it down in case I need the value later:
Code:
mov eax, 0x8E42B0
Let's see where that takes us:
[Image: 0d92e39018722baa3b921cb4c5b332bf.png]

So this time, an integer (32bit) is being pushed into the accumulator. Nothing really to follow here, especially when there's a ret instruction shortly after, so we need to actually think back to the explanation I gave earlier of how packers work.
They jump around, decrypt, then jump around again. It looks like the accumulator is also being used as 'storage' for where the instruction pointer should jump around to, so let's see what returns when I search for:
Code:
jmp eax
[Image: c0501a1d2a5b9f7164a1128ede560eb8.png]
[Image: 6f301682502925c912054dcee67ce359.png]

Two results only. That narrows it down quite a bit.
Now let's go back to our noted down asm instruction:
mov eax, 0x8E42B0

0x8E42B0 is much bigger than 0x8DFB5B, so that probably won't be it.
Instead, I'll attach a breakpoint to the second option, since it does come after where we just were.
And now, all that's left to do is hit the 'Run' button at the top.


You see, although we're in this weird disassembly mode, we're not trying to get a disassembled raw source; we're looking for the original source. At some point in this program's execution, that original source will be visible, even for an instant, because the program needs to decrypt it first then start execution. So we let the program handle the heavy-lifting and reap the rewards, hence we just start running it.


So hit run/step a few times until we get to the jmp eax instruction. What you'll notice is that in the comment beside (that x64dbg generates on its own,) is that eax = the original EntryPoint we had, just as I predicted.
[Image: 20028fffa11510533536a6b1158b49ab.png]

Now, just take one more (single-instruction) step to get to the real Entry Point of the application:
[Image: a9df71761ad67e3cfea3ce94e92a24a1.png]
And now, we actually recognize a few things on the screen. There are actual function names, for a start. This is the real packed program. Now all that's left to do is dump it.
So we open the Scylla toolkit. Keep 'Attach to Active Process' selected, since it's what we're debugging. And since Scylla has some decent automation, we just hit IAT Autosearch.

IAT means the import address table, ie. all the libraries and whatnot that are being imported.

Then, smash 'Get Imports'
[Image: 94087bb6374caf8311a0cf7b3f8a92c7.png]

Okay, there are errors. For whatever reason, whatever we dump probably won't run properly.
f*** it, the trainer was already broken. I'm looking to extract a resource, not fixing the f*** code.
Hit dump, save the file, and get out of there, since we're done with the debugger.



That was the worst of it. Now we have a few options:
--Since the file was packed, it didn't open in dotPeek. The resources were also hidden in ResourceHacker.
--I can binwalk/search for file headers with a hex editor.

First I tried dotPeek:
[Image: dfc2640065b551b230818bd5405ef509.png]
Two in a row. One more failure and I get a hat trick.
Next, ResourceHacker:
[Image: 696c0467f91f8966851e5e9da9596b62.png]

I noticed that there are a couple of WAVE (.wav) files there, a total of five. There are also some custom files, but they don't seem to dump properly with reshacker, so that's a no-go.
When looking through a file to find different types of files, we need to look for file signatures, ie. magic numbers. It's usually the first four to eight bytes which define what a filetype is and how to open it. Funnily enough, the .zip magic numbers are used for almost everything, but that's a story for another time.

When searching WikiPedia's list of file signatures, I found .wav:
Code:
RIFF....WAVE
The 4 dots represent a 32bit integer for the size of the file.

I know there are five of these files embedded in the .exe. So let's pop it into my favourite Windows hex editor, HxD, and try to find these headers:
[Image: 3734acf453e9dafa9dc0d840329d80a0.png]
Okay, the first one is at 0x3D4AE0. I highlighted the four bytes between RIFF and WAVE which represent the file size. On the right-side, I highlighted the int32 number: 147494
And from 0x3D4AE0 to 0x3D4AE0+dec(147494), I copied and pasted the data into a new file, saved it as Untitled.wav and played it in WinAMP.

And you know what I got?
A f*** Windows Vista error/info sound.
The developer of this trainer used them as the sound effects for turning cheats on/off, or as extra sounds.
And every single .wav file was like this.
Almost defeated, on the last .wav file, as I was selecting the block for the file size, I saw something:
[Image: 9a4c24df1247e29556a16cf9eeff99c8.png]

And I was f*** ecstatic. Honestly I still am, it's been almost nine f*** years.
After a quick google search, I found that Extended Module refers to a demoscene file format, .xm, which was popular back in the day of music trackers (what came before FL Studio.)
And after another search, I found a download of FastTracker, the one used to make this track:
https://www.pouet.net/prod.php?which=13350

So I downloaded it and got the .exe
And it only runs on MSDOS, it's that old.
Nothing an emulator can't fix, but that means more setup.
There was another file included, XM.txt
And just my luck: it was the entire documentation of the .xm file format, like all its file header information and how the data is structured.
God bless the demoscene, absolute madmen.

So after reviewing the docs and putting everything together, I finally extracted the full file from the unpacked .exe.
And I was going to go find a program that plays .xm files, but I realized that WinAMP has that support built-in, so I don't even need to reconfigure.
Absolutely amazing.

And now I'm going to convert this to a .wav or .flac and keep it safe for the rest of my life so I never need to go through that process again.
Here's the download link:
http://www.mediafire.com/file/zmy7kor1ko...ry.xm/file
It'll play natively in WinAMP, as mentioned. Not sure about other programs, but you can also install xmp (google it) as an alternative.

Maybe you won't like the song as much as I do. To be honest, it's lost a bit of its lustre, but it still held that sentimental value of playing Black Ops with the boys back in middle school, and that's a d*** good feeling.

Print this item

  What is the most toxic job you've ever had?
Posted by: Darth-Apple - October 24th, 2019 at 9:40 PM - Forum: General Discussion - Replies (1)

For me, it was a restaurant that I worked at for quite a while. I put in plenty of grit and gave that place as much energy as I had to give. I finally had had enough and quit. And once I quit, I realized I had my life back... 

I was a line person, generally was the lead person on the weekends. That involved being in charge of basic things on the line, and I was the point of contact for anything that happened. Whether something needed to be remade, or a mistake was made, or an order was changed, or we were being too slow, I was the one that heard about it. I was the one who delegated the work, and more or less ran the line and opened the kitchen on the weekends. 

I trained many people over the years on that job, and almost always got great reviews from my trainees. Another store opened up, and I trained several of the people who ended up opening the new store (INCLUDING the manager of that store, who ended up transferring and soon managed me.) So yes, I quite literally trained my own manager. I felt my performance was good, but I will explain why I ultimately left. 

  • It was an incredibly clique-ish environment. There were two primary cliques, and a few smaller ones in the mix. 
  • The cliques usually hated each other, and passionately so. If you were in one clique, the other one hated you. 
  • There was a manager that was very involved in the gossip and drama, and usually instigated it. This manager pretty much knew everything there was to know about anyone who worked there. If it happened, he'd know about it, and he'd gossip about it. 
  • The work parties were a BIG, BIG deal. You had to be in the in-group to be invited. If you weren't invited, you would generally not get hours at work or otherwise be treated poorly. Usually a manger would attend these parties, and would occasionally snitch on people they didn't like to the gm. 
  • Managers would make sexual jokes about female people on the job. If the guys on the line didn't join in, they were called many derogatory things. Usually they were called gay, whether they were or not, and yes, this was meant in a derogatory way. (Offensive, as there were people who were gay on the job, and should not have to be around having the term used in a derogatory way)
  • If you were a relatively nice person, you were instantly a target. Neither group would really accept you. One group would tolerate you, but gossip about you behind your back. The other group would pretty much blatantly refuse to talk to you. 
  • If you were disliked by someone, they'd usually make up anything about you. People would believe it quickly. You'd be accused of cheating on your significant other (without any merit whatsoever), or of coming into work under the influence, or of other horrible things. Usually these were completely false, but people believed it regardless. 
  • Speaking of which, if someone was excluded by your clique and you talked to them, even to say hi, and interacted with them in any meaningful way, you would generally be pressured to stop. If you didn't, you'd be excluded yourself. 
  • One of the managers was very close friends with a couple of people in particular on the line. These people had their heads high in the air, and would be very entitled in general. If they wanted to date you and you didn't like them back, there went your hours. Because this manager was the scheduling manager, and would make sure you were retaliated against. 
  • The hours, speaking of which, were all over the place. They would promise you 30, give it to you one week, and then cut you to 15 the next week for no reason. Often you were scheduled against your availability. If you got a second job, they purposefully scheduled you against your availability, and would write you up if you called out for your other job. 
  • If the manager heard some gossip about you and wanted to retaliate, he'd completely remove you from the schedule after you were scheduled and give the hours to someone else. This actually happened, multiple times! 
  • I was the head person on the line for the weekends. The weakday line lead was extremely mean. I was far, far more liked than she was, and she was generally jealous if anyone was likeable. I had many, many people come up to me and thank me for being far more approachable, unlike her. She went and tried to tell the manager I was bad at my job and tried to get me fired for it. 
  • Anyone who quit would be fair game for gossip. And it'd be rather extreme. Generally, if you quit, you were not rehireable, no matter what. Many people would unfriend you on social media, and pretty much everyone would stop talking to you. 
  • It was basically a cult. They were convinced they were the best job ever, and that you were never going to find anything better. If you disagreed with them, they'd put pressure on you by excluding you. You were almost always passionately hated by at least three or four people in the store, all of whom would work vehemently to damage your reputation. 
  • I quit. Luckily, I was not unfriended by the entire staff. I did, however, unfriend the managers. I still talk to a few people, but by and large, I'm glad to be gone. 
 

I used to sell cars. Even the sales floor wasn't as bad as the restaurant described above. 

What's your most toxic work experience? Looking forward to seeing your guys' responses. I'm sure there will be some good ones.

Print this item

  General linux thread
Posted by: SpookyZalost - October 23rd, 2019 at 7:01 PM - Forum: Software - Replies (13)

so I know there's a bunch of dedicated linux threads but I wanted a general one for general linux discussion.

so for anything relating to linux that doesn't have or need it's own thread, like usage, setups, etc, general discussion on the topic.

so what do you guys run as a nix box?  and what are your thoughts/experiences with it?

Print this item

  Cracking Hashes with Arduino
Posted by: Lain - October 22nd, 2019 at 3:54 AM - Forum: Technology & Hardware - Replies (3)

Cracking Hashes With Arduino
Written by Lain; Released under GPLv2 License; Published for Makestation

Table of Contents:
0x00 - Introduction/Materials/Disclaimer
0x01 - Setting up IDEs/Toolchains/Drivers
0x02 - Setting up your Arduino Board
0x03 - Basic Hashing Logic
0x04 - Hashing a Serial Command
0x05 - Communicating with Python
0x06 - Automating the Process
0x07 Making it Fast
0x08 - Conclusion


0x00 - Introduction:

Welcome to the guide. This project has been in the works for a month or two, just working on-and-off. That doesn't mean it's very complex, it's actually rather simple once boiled down, and I've added lots of comments to make it super-easy to understand. That being said, I will assume at least some degree of programming competency (I'm not explaining what a for-loop does. Figure it out yourself.) I'm also assuming a very basic degree of competency with Python and Arduino language in particular, but since they're still very basic, that shouldn't be much of an issue as long as you still have some degree of knowledge generally.

The complexity of this project arises from two points: understanding communication between devices and understanding timing. You'll see what I mean as I dive deeper into the later-stages of the project. These concepts are explained to the best of my ability.

If you're unfamiliar with the concept of a hash, then I'll give you a brief explanation:

When you login to a website (like Instructables) with your password, the password stored on the website generally isn't the password you send (under good security conditions.) Instead, the server will store something completely different, so in the case that it gets hacked, your password is still unknown to the attacker. That different 'password' is what you call a hash, and it's NOT actually encrypted. With encryption, you can decrypt the message, but in the case of hashing, you cannot generate the original string from the generated. Thus, to break or 'crack' a hash, we simply try all sorts of permutations until we find one that works and generates the same hash value, and we consider this to be the 'original.'

If you're involved in the security scene, or keep up-to-date with all sorts of data breaches, then you're probably aware of this fact, and you're probably also aware that this type of attack is called 'brute-forcing.' If we had an unlimited amount of time and power, we could theoretically brute-force (crack) any hash possible. Unfortunately, we don't have unlimited time, but with enough power on our computers, we could still crack many hashes in a relatively short amount of time. In modern days, we use graphics processors (graphics cards, or GPUs) to crack hashes since they can handle many computations at once.

The trade-off for the massive amounts of power in your GPU or computer is that we use lots of power, literally! The voltage to keep these setups running will make your power bills spike through the roof, and we could even call it unsustainable.


What you'll need:
  • An Arduino board (I'm using a MEGA2560 clone from China)
  • A cable to plug it into your computer
  • Your computer
  • The Arduino IDE 
  • The Python3 Toolchain
Optionally, you may also want to install the PyCharm IDE which is what I use for the Python segment which I use in sections 5 through 7.

DISCLAIMER: This project was initially uploaded to Instructables as an entry in a contest. The Instructables team have since unpublished the project as a violation of their ToS (no password attacks or hacking-related content.) I don't blame them for it and hold no hard feelings, and will instead come up with a different project to publish, maybe along the lines of blockchains and IoT.

I actually do agree with their ruling, since this project can potentially be used for malicious purposes, and as part of the disclaimer, I hold no liability for damages incurred as a result of this project and guide.

By extension, due to the GPLv2 license used in this guide (and respective code samples,) I do not provide any warranty and support. Everything is provided AS-IS. That being said, I will update the guide as I see fit (if I notice typos and whatnot.)

Without further ado, let's start walking through some basic setup.


0x01 - Setting up IDEs, Toolchains, & Drivers:


It sounds like a lot, but I promise it really isn't. First, you'll need the Arduino IDE.
You can install it from the official site here, just choose the version you'd like.

Since I'm using Windows, I installed the Windows Installer package. I am an administrator on my own computer.
I chose the installer over the Windows Store App for two reasons:

  1. The Windows Store version is usually a version out-of-date. At the time of writing this, the Windows store version is on 1.8.9 and the installer is on 1.8.10.
  2. Since Store apps install to a different location and use different defaults, you may need to adjust/adapt to later steps when installing libraries.
In the options screen of the Arduino installer, this is what I have set:

[Image: BFQRQ3g.jpg]

To ensure that your board will work, select the Driver option. For easier development later on, you can select the .ino file association as well. Shortcuts are optional, since I don't have icons on my desktop, I don't need one there. Instead, I launch everything from Start menu.

Let the installer finish, and finally, allow the driver installation pop-ups you get. Your board won't work without them.

Congratulations! the Arduino IDE is installed. To ensure that it works, run it from one of the shortcuts or from your install path.

Installing Python

If you don't actively develop with Python, you'll need to install it now. but if you do develop with Python, first check that you have the correct version.
For the scripting in this guide, I use Python3 as it's the latest and greatest with long-term support. If you think you have Python installed, then run this in your command line:
Code:
python --version
If you get anything that isn't a 3.X.X version, then check to see if you might have it installed side-by-side with python2:
Code:
python3 --version

If you get an error saying command not found, you need to install it. If neither of them return a version number that starts with 3, you need to install 3 (or port the script part over for your respective version.)

Go to the official Python website and hover over Downloads. You'll see the 3.8.0 button (at the time of writing this.) Click that button; it's a direct download so give it a second to start. If it downloads the wrong type of file for your platform (might be different for MacOS or Linux,) click All Releases and download your respective version.

In the installer, make sure that you check the box saying you'll add it to the PATH variable. This is critical for running Python from the command-line. Select the rest of the default values (or the Typical/full install with pip) and let it run for a minute or so until it finishes installation. All set!

Optional: Installing PyCharm

As stated, this is optional. I use PyCharm as my Python editor/IDE since it's just a little easier to use when everything is all in one place. You don't need it, and if you're familiar with a different text editor and manually running scripts, then you should just stick to that.

As before, head over to the official website. Select your OS and select the Community edition. We're not selling this project, so we don't need a commercial license that Pro gives us.

Once it downloads, run the installer. Once you get to the other options, just know that I have everything checked. If you don't understand what the option does, then you should probably leave it alone. But most modern computers are 64 bit, so you can add the 64 bit launchers if you'd like.

Let it install, and once it's done, you may be prompted for a reboot. I'll tell you now, you don't need it. If you want to reboot your PC, more power to you. But if your PC takes 5 minutes to start up, then you don't need to.

After all this is done, you should be ready to start setting up your Arduino board!


0x02 - Setting up your Arduino Board:

As a sidenote: I'm using the MEGA2560. It's a clone from China because they're much cheaper than the 40$+ on the official website. That being said, you don't need a MEGA2560. An UNO will do, or the tiny little Nano or Pro Micro. This Arduino code is relatively portable and works fine with other boards with minimal modification, if any at all.

The Arduino IDE will default to using the UNO since it's by far their most popular board. In my case, I need to do additional setup (and you should probably make sure everything here is set properly too, thus I'm not considering any of this optional.)

First, open the Arduino IDE you installed and you'll have yourself a nice blank sketch. At the top-bar menu, go to Tools > Board: "XXX" > Your board, as shown in the image below:
[Image: nEOHfMr.jpg]

Since I'm using the MEGA2560, I selected that one. Choose which one your board is (and make sure it's plugged in.)

Next, we need to set the COM port, or how the Arduino will communicate with the computer to get programmed. Since I'm on Windows, I'll show you how to do it on Windows and leave other OS's to Google.

Open the Start Menu, type in 'Device Manager' and hit enter (or select the device manager from the search bar.) In the new window, scroll down to Ports (COM & LPT) and expand the menu. You may see a few options, as shown below.
[Image: pdcm7lP.jpg]

We're using USB for communication, so select the one that says USB and not Bluetooth or anything. Take note of the actual port number beside it (in my case, COM5) and head back to the Arduino IDE.

Back to the top-bar, go to Tools > Port and select the port number you noted from the Device Manager earlier.

To make sure the board is working, go back to Tools and this time click Get Board Info. If you set it up properly, you should get a little pop-up dialog box like below:
[Image: QOV0OCn.jpg]

In my case, the actual board cannot be retrieved because it's a clone from China and not an official board. If you have a clone, don't worry about it not appearing there. As long as you get a dialog box of some sort, you're all set.

If not, run through these steps again or Google for troubleshooting. I don't provide warranty and support.


0x03 - Basic Hashing Logic:

So we have everything set up, meaning it's time to bunker down and start programming!
As mentioned in the intro, the only way to actually 'break' a hash is by testing a million different things to find a hash that matches, and we consider the matched hash to be the 'original' string of data.

So for our Arduino to crack hashes, we need to actually implement the ability to hash things with Arduino!

Now, it's a little more difficult than that: there are tons of hashing algorithms out there. We need to consider a few things:
  • How fast is the hash?
  • How easy is the algorithm to implement?
Arduino isn't the most powerful device in the world. Far from it, actually, even considering the world of microprocessors it's pretty slow. So we want our algorithm to be fast. But fast algorithms also come at a price of security, since we could theoretically check many more hashes in a short amount of time than a more complex and slow algorithm. But, because Arduino is inherently not as powerful enough to hash things quickly, we want something that's pretty fast so that we can still get decent performance from the device.

Thus, I propose MD5 which has been used for over a decade, and is slowly becoming obsolete in the shadows of other great and slower algorithms.

MD5 is great because there are implementations everywhere. RosettaCode has tons, and if you've checked, they have an implementation sample in C. And if you've used Arduino before, you're probably thinking: "Hey! ArduinoLang is almost like C, so if we copy/paste it, it should work! Right?"

And the answer is no, for two reasons: Architecture and Pointer arithmetic. Since hashing is generally done straight in memory (especially in the C sample,) pointer arithmetic varies from x86 architecture (like your computer) and ARM/RISC architecture (Arduino). So we may need to re-implement it.

But fear not! For a great Greek programmer has come to our aide a year in advance, releasing a library that does MD5 hashing for us in Arduino! I present to you: ArduinoMD5, by Tzikis all available on GitHub.

Follow his installation instructions. You may need to alter his instructions if you are on a different OS than Windows. Remember to restart the Arduino IDE after installing it.

To add the library to our sketch, open up the Arduino IDE, and on the first line, link the library:
Code:
#include <MD5.h>
Alternatively, go to Sketch > Include Library > Contributed Libraries > MD5
If you don't see it there, you installed it wrong. Restart your Arduino IDE and try again.

Since Tzikis also included a usage example, I've added some slight modifications and turned his example into a standalone function:
Code:
[color=#333333][size=small][font=Monaco, Menlo, Consolas, ]void hashMD5(char a[]){
 unsigned char* hash = MD5::make_hash(a);
 char *md5str = MD5::make_digest(hash, 16); //Direct example from Tzikis's GitHub.
 for(int i = 0; i < 32; ++i){
   returnVal[i] = md5str[i]; //Assigning the global variable character by character.
 }
 returnVal[32] = 0x00; //Always null-terminate your strings, kids!
 free(hash); //Since we're looping, we need to free up the memory before another iteration.
 free(md5str);
}[/font][/size][/color]

Read the comments, but the function takes in a byte-array (C string) and instead of returning the value (void-type function,) will modify a global variable instead, allowing us to free up the memory again for more iterations.
If we don't free the memory from the algorithm, we risk overflowing the on-board memory on the Arduino.

At the same time, we should also add the global variable listed. Right beneath the import, define returnVal as:
Code:
char returnVal[33];

Now, why 33?
MD5 only spits out 128bit messages in hexadecimal format. A hexadecimal digit uses four bits, so naturally, 128 / 4 is 32.
And why 32 + 1? Because you always need to null-terminate your strings so you don't overflow memory (the program will generally stop reading the array once it encounters a null-byte.) That's why we assign the last byte after the loop in the function to 0x00, a null-byte.

Now, we want to actually send/receive data later on, so we need some sort of communication and actually read the data we get, so we should start setting up our setup() function in the sketch:
Code:
void setup(){
  Serial.begin(9600)
  delay(500) //Half a second delay, just to ensure everything starts up properly.
}

The delay isn't really needed, but I like to include it as a safety net in case something does go terribly wrong.
The 9600 is the baud rate. More on this in the next section.

Finally, we want the program to actually use that fancy MD5 hashing function we made, so in the loop() function, I wrote this:
Code:
void loop() {
  hashMD5("a"); //Hashes the 'a' character.
  Serial.println(returnVal);
  delay(1000); //Unnecessary, but for the sake of readability and a slow Serial monitor.
}

Now verify the code with the checkmark button in the upper-left to make sure it compiles. You may be prompted to save now, if not during upload. If it passes (you may get a warning or two from the library, these are fine,) then upload the code with the button right beside the checkmark. 

To see if the code works, open the Serial Monitor by pressing CTRL+Shift+M or going to Tools > Serial Monitor. If all went well, you should start seeing a weird string in the monitor every second: 0cc175b9c0f1b6a831c399e269772661. This string is the hash value of the character 'a' and it's exactly 32 characters long.

To test this, go to MD5 Hash Generator, type in 'a' (without quotes and no newlines) and hit 'md5'. Success!

But we're not trying to hash 'a' over and over again, we need to be able to input any arbitrary value we want to test, so let's implement some user-input!


0x04 - Hashing a Serial Command:

Now, I know what you're thinking:
"Lain, I don't want to type in thousands of strings myself to try and crack stuff!"
And don't worry, we'll get to automation later on with some more scripting. But to be able to run, we first need to walk. Right now, we're still crawling.

When the Arduino was communicating the hash to us, it was using the Serial System over the COM port we found earlier and set up (COM5 for me.) Serial is great, but it has some specifications we need to be aware about:
  1. Serial implies 'Series'
  2. It has a maximum value.
Serial is derived from the word 'series' and that means that the data it sends is in series, byte-by-byte and bit-by-bit. So we need our program to read the data sequentially.

The max value is defined by the Arduino board: All boards have a Serial buffer that can only store so much incoming data (or outgoing as well, for that matter.) That max value is a total of 64 bytes, or 512 bits. So when we store that data somewhere, we should have a buffer ready. Define a new global variable: buf:
Code:
char buf[64];

We don't need to null-terminate this one, since it's the max value anyway, and if you think about it, you and I don't use 64 character passwords. If you're ultra-paranoid, yours is still probably only around 25-30 characters. That being said, we should also write a function that clears the buffer out after every iteration:
Code:
void clearBuffer(){
  for (int i = 0; i < 64; ++i){
    buf[i] = 0x00;
  }
}
Self-explanatory, I hope.
We need this function because if we put in a password like 'zer0cool', the buffer will fill, get hashed, spit out to the Serial Monitor like before, but then wait to receive a new pass, let's say 'lain' and will then fill the buffer for the first four bytes. The rest of the buffer will still be 'laincool' since there's residual data from the last password.

Thus, we write null-bytes over the whole d*** thing every time.

Now, to actually get data from Serial, we need the help of two functions:
Code:
Serial.readBytesUntil() //Reads the actual data in the buffer
Serial.available() //Returns the number of bytes in the buffer

So, we'll have the loop function check every time whether there is data in the buffer, and if there is, start reading the data. You might propose something like this:

Code:
if(Serial.available() > 0){
  Serial.readBytesUntil();
}

First, I'll call you out on the condition. Anything greater than 0 is considered true, so we could shorten the condition and save a few bytes.
But you have overlooked our Serial definition above. Remember, Serial is sent in a series of bytes, not all at once. On one iteration of the loop, it may return 0, meaning no data, and the next it'll return one because there is a new byte there (or maybe four, or however much was sent in the duration of that loop.)

But it might only read a few bytes, while more data is still being sent. If it returns 4, that's cool, maybe there are currently four bytes in the buffer, but you might have sent 16 bytes, and it's in the process of sending that data, so it'll only read part of that data, hash it, spit it out, and then check again for more data, which leads to more problems.

So instead, for the time being, let's add a short delay to make sure all the data gets sent before we try to read it. While using proper function arguments, we'll end up with this kind of main loop():
Code:
void loop() {
  clearBuffer();
  if(Serial.available()){
      delay(10);
      Serial.readBytesUntil('\n', buf, Serial.available());
      Serial.println(buf);
      hashMD5(buf);
      Serial.println(returnVal);
  }
}

In the readBytesUntil() function, we are using '\n' as a terminator; once the program reads this byte, it will discard it and consider it the end of the string. We will need this later, but it's also helpful right now, as seen in the demo below.

I've bumped up the baud rate (Serial.begin() in setup() ) to 115200. The baud rate is the rate at which data is sent, in bits. So 115200 bits per second.
Since we're sending a maximum of 512 bits at a time, 512 / 115200 = 0.0044...
So about four/five milliseconds should be enough for transferring all the data. To play it safe, I added a delay of 10 milliseconds, which we can optimize later.

Our final program once put altogether will look like this:

Code:
#include <md5.h>
char returnVal[33]; //An MD5 hash is ALWAYS 32 characters long, or 128bit. Add an extra byte for null-termination.
char buf[64]; //The max Serial buffer is 64 bytes.

void setup() {
  pinMode(2, INPUT_PULLUP); //Unnecessary at the moment, will be needed later.
  Serial.begin(115200);
  delay(1000); //A second to start up properly.
}

void clearBuffer(){
  for (int i = 0; i < 64; ++i){
    buf[i] = 0x00;
  }
}

void hashMD5(char a[]){
  unsigned char* hash = MD5::make_hash(a);
  char *md5str = MD5::make_digest(hash, 16); //Direct example from Tzikis's GitHub.
  for(int i = 0; i < 32; ++i){
    returnVal[i] = md5str[i]; //Assigning the global variable character by character.
  }
  returnVal[32] = 0x00; //Always null-terminate your strings, kids!
  free(hash); //Since we're looping, we need to free up the memory before another iteration.
  free(md5str);
}

void loop() {
  clearBuffer();
  if(Serial.available()){
      delay(10);
      Serial.readBytesUntil('\n', buf, Serial.available());
      Serial.println(buf);
      hashMD5(buf);
      Serial.println(returnVal);
  }
}

Upload the sketch and wait a second.

Open up the Serial monitor again (CTRL+SHIFT+M) and instead, you won't see the same hash running down the screen. In fact, the screen will be empty. Notice the little message box at the top. Type in 'a' and press Send.

You should get the same hash value as before. Try it with different letters, or even full words, or even sentences (below 64 bytes, though!) Notice the bottom of the screen a little dropdown menu with the word "Newline". That's the '\n' terminating character we used before for readBytesUntil(). Changing it may break the program, but we will account for it later, since we need a terminator of some sort anyway.

Now we have a cool hashing machine, and it's pretty fast at actually hashing stuff! And, like I promised at the beginning of this stage, we're going to automate the process so you're not typing stuff in over and over again. User-Input really means Machine-input for where we're going next.


0x05 - Communicating with Python:

Fire up PyCharm (or your favourite text editor) because we're starting the automation process.

Make a new file/project and call it something like script.py or main.py. It really doesn't matter. add two imports: sys and time as so:
Code:
import time
import sys

We need sys for the exit function and we need time for the delays and ensuring synchronization between serial I/O (as we did in the Arduino sketch.)

Now, we need a way for Python to interact with the Serial device, ie. Arduino, so I found a relatively well-maintained library for doing just that (and it supports Python3.) It's called pyserial.

If you installed pip with Python, then open up a terminal and type in:
Code:
pip install pyserial
If you get an error, make sure that pip is installed somewhere, and also make sure you added Python to your PATH from the installer. Again, no support if these don't work for you or you have no idea what I'm talking about. Google it.

When using this library, despite it's name being pyserial, we imposrt it as just 'serial'.
Code:
import time
import sys
import serial

We should also specify our COM port and baud rate as we did in the Arduino sketch/IDE:
Code:
baud = 115200
port = 'COM5'

115200 is the baud rate we used in the sketch, so naturally we want it to be the same. COM5 is my port. Remember to specify it as a string (use the quotes.) Change the port if necessary to your own.

To actually use serial communications, we need to create a serial object from the library and by following the official pyserial docs, we instantiate the object like this:

Code:
ser = serial.Serial(port, baud, timeout=1)
time.sleep(1)

The only really important parts are the port and baud rate, everything else is secondary. The timeout is there to make sure that the device has at least a second to respond, else it'll be a failed connection. I also add a sleep of one second to make sure that the device isn't in the process of timing out before we do anything else.

Add one more line to print the object, and run the script:
Code:
print(ser)

By instantiating the serial object, the connection is automatically opened and we can start using it, no need for more functions. So after the sleep, we just print the object data and you should see a property that looks like this:
Code:
open=True

If you did, congratulations! You can now communicate with the Arduino and we can move on!
If not, check your COM port and make sure you changed the baud rate in the Arduino (or change it to whatever you'd like, as long as the number is the same in both the script and the sketch.) No more support.

Now, we're going to use some actual serial functions in python:
Code:
Serial.write() // Same thing as Arduino Serial.print()
Serial.flushOutput() //Clears the output serial buffer
Serial.read_until() // Same thing as Arduino Serial.readBytesUntil()
Serial.close() //It's always good manners to close a connection when you're done with it.

So let's put it all together!
Code:
import serial
import time
import sys

port = 'COM5'
baud = 115200

ser = serial.Serial(port, baud, timeout=1)
time.sleep(1)
ser.write(b'a\n') #You can only write bytes data, so we do the conversion from the string 'a\n' 
ser.flushOutput() #Once sent, PySerial does not clear the output buffer on its own, so we need to do it manually.
time.sleep(0.010) #Give the device ten seconds to receive some data back
hashVal = ser.read_until(b'\n', 32) #Will read until it either finds a newline character or until it reaches the maximum of 32 bytes.
print(hashVal) #prints the received data
ser.close() #Good manners
sys.exit()

The comments should be verbose enough, but I'll explain the write() part a bit more.
It's not pythonic. I know. F**k your PEP8 standards, I don't care. I'll change it later, I promise. What's important is that we add that newline character, '\n'. It's important because that's the same terminator we used in the sketch on the arduino:
Code:
Serial.readBytesUntil('\n', buf, 64)

So it'll stop reading the buffer once it reaches that \n, and won't include it, meaning faster read times giving us more time to compute the hash.
Since we are only sending 32 bytes at a time from the Arduino, we only need to receive 32 bytes, hence the value defined in read_until().

Run the code, and if all goes well, you should have this output:
Code:
b'0cc175b9c0f1b6a831c399e269772661'
Because we're printing bytes values, it's encapsulated in the b'', so don't worry about that. We'll fix that later.

One more thing we want to add. We're doing this whole thing with Python for the sake of automating the process, so let's actually automate it with a hard-coded list. Let's change up the script really quick:

Code:
import serial
import time
import sys

port = 'COM5'
baud = 115200
passes = ['a','b','c','d','e'] # List of things to hash

ser = serial.Serial(port, baud, timeout=1)
time.sleep(1)
for item in passes: # loops around for each item in the list
    ser.write(item.encode()) # a more pythonic way to encode to bytes
    ser.flushOutput()
    time.sleep(0.020) #Give the arduino a few more milliseconds for synchronicity
    hashVal = ser.read_until(size=32) #We don't really 'need' the terminator if we only read 32 bytes.
    ser.flushInput() #Safety of clearing the buffer once we read it.
    print(hashVal.decode('ascii')) # a more pythonic way of decoding bytes to text
ser.close()
sys.exit()

And now, the output should be this:
Code:
0cc175b9c0f1b6a831c399e269772661
92eb5ffee6ae2fec3ad71c777531578f
4a8a08f09d37b73795649038408b5f33
8277e0910d750195b448797616e091ad
e1671797c52e15f763380b45e841ec32

Each character gets passed to the arduino and hashed!

We don't want to hardcode our list of words to try, so let's add some logic to open a file full of words, parse it, and while we're at it, add a check to see if we match a given hash to break.


0x06 - Automating the Process:

I'll cut it short since this is starting to get lengthy. To open a file, we don't need any additional libraries, just this little code snipped at the top with our variable declarations:
Code:
file = open("list.txt", "r")
if file.mode != "r":
    print("Unable to open list.txt in current directory!")
    sys.exit()
lines = file.readlines()
This opens the file and splits it based on each line. Each line in our file should be one word/character to hash.

We should also add a declaration for a hash to crack:
Code:
toCrack = '8277e0910d750195b448797616e091ad'

Since we're now using a different list, we should modify the loop, and actually add a conditional to check of the received hash is the same as the toCrack hash. Here's the full code:
Code:
import serial
import time
import sys

port = 'COM5'
baud = 115200
file = open("list.txt", "r")
if file.mode != "r":
    print("Unable to open list.txt in current directory!")
    sys.exit()

lines = file.readlines()
toCrack = '8277e0910d750195b448797616e091ad'

ser = serial.Serial(port, baud, timeout=1)
time.sleep(1)

for line in lines:
    ser.write(line.encode())
    ser.flushOutput()
    time.sleep(0.020)
    hashVal = ser.read_until(size=32)
    ser.flushInput()
    if (hashVal.decode('ascii') == toCrack):
        print("Found! -- " + line)
        ser.close()
        sys.exit()
ser.close()
sys.exit()

To make this script work, put a file in the same directory as the script you made and name it 'list.txt'. make the file read as follows:
Code:
a
b
c
d
e

See the image below:
[Image: 39T5jtI.jpg]

Once the file is made and in the same directory (with the same name,) run the script. You should now get this output.
Code:
Found! -- d
Congratulations! We've finally made a hash cracker with full wordlist support! The prototype works and can be considered complete now, except me being me and wanting optimization, I took it another step further.


0x07 Making it Fast

Remember those delays we added everywhere to make sure it would synchronize properly? Those are eating tons of time. Taking the largest one of 0.020s in the Python script, we could only compute a total of 50 hashes per second, which, although sounds high, is actually incredibly small. To increase the speed, the first place we're going to look is to take away the delays.

To fix the Arduino sketch and its 10ms delay, I've opted for this solution:
Code:
void loop() {
  clearBuffer();
  if(Serial.available()){
      Serial.readBytesUntil('\n', buf, 64);
      if(buf){
          hashMD5(buf);
          Serial.print(returnVal);
      }
  }
}

Not much different, and it makes sure the buffer really is empty before trying again. I've also changed Serial.println() to Serial.print() so it doesn't send the newline characters \r\n.

And to fix the Python delays, I've opted for this:

Code:
for line in lines:
    ser.write(line.encode())
    ser.flushOutput()
    while ser.inWaiting() < 32:
        continue
    hashVal = ser.read_until(size=32)
    if hashVal.decode('ascii') == toCrack:
        print("Found! -- " + line)
        ser.close()
        sys.exit()
    ser.flushInput()
ser.close()
sys.exit()

The script will actually stop at the while loop until there are at least 32 bytes and it'll only read 32 bytes at a time. The flushInput() probably isn't necessary anymore since the buffer should be clear after the read and have no terminating characters, but it's still there for safety.


0x08 - Conclusion:

Now, the project will crack hashes at approximately 150 hashes per second, or about three times faster than before. That's great to hear. The only remaining time to optimize upon is:
  1. The optimization of the hashing algorithm implementation
  2. The transfer time over Serial.
Now, 1. isn't so easy to fix, but 2. could be made faster by simply increasing the baud rate. Since I wanted to keep this project as contained as possible (ie. no shields, no wires, no bullshit,) I didn't use any other peripherals. But if you stored a wordlist on an SD card and used a microSD shield, you could get rid of 99% of the Serial communication time by only sending the hash to crack over serial, then waiting on a response from the Arduino, while the Arduino pulls words to hash from the SD card and does the computations, only sending back a message if it found or didn't find the hash, and what the original string is. This is where you'd go in the future for optimization.

Overall, it was a fun project, and even I learned a lot about Serial communications over the duration. It's a shame that Instructables unpublished my guide, but I guess that's just an opportunity to bring one of my other ideas to life, and the opportunity to write everything here instead (congrats, you're now the only website online that is hosting this guide publicly!)

I've attached the final files as well, the Sketch.ino Arduino sketch and my main.py Python script.

If you make it or if you optimize it, let me know! Learn from it, build it, build on it!

~Lain

Print this item

  Consumer VS Maker
Posted by: SpookyZalost - October 18th, 2019 at 2:22 AM - Forum: General Discussion - Replies (6)

Are you a consumer, someone who pays money to corporations and buys the latest toys, or are you a maker, someone who actually learns skills and crafts things?

personally I lean more on the maker side of the spectrum, I buy broken stuff and repair it if I really want something (usually at a cheaper cost), I like to tinker with and prefer technology that I can do something with rather than something that has a per-determined purpose, technology that can be modified and changed when the need arises.

recycle, restore, refurbish, and Craft.

but I know there's people on both sides.

so what's your opinion, do you side with the consumers and big corporations?
do you side with the makers, crafting things, recycling, and finding new fun ways to approach things?
somewhere in between?
or something else?

Print this item


Dark/Light Theme Selector

Contact Us | Makestation | Return to Top | Lite (Archive) Mode | RSS Syndication 
Proudly powered by MyBB 1.8, © 2002-2025
Forum design by Makestation Team © 2013-2025