Building Merikens Tripcode Engine on Linux in 2020

The engine running, generating ~1 billion tripcodes/hashes per second

Intro to tripcodes

Odds are if you’re reading this page you already know what Meriken’s Tripcode Engine does, but in case you stumbled here unaware and are interested, I’ll give a brief and incomplete history lesson on tripcodes and bruteforcing them to get a desired outcome. Tripcodes are used on various image boards on the internet to uniquely identify posters. Most of these sites do not require or even allow users to register but do allow them to choose a name when posting. Usually, posters choose to remain anonymous but there are times when it can be important for a user to be identifiable over the course of a discussion.

If the user chooses to use a name, there is really nothing to stop another user from choosing the same name: enter the tripcode. By appending # to your name and adding a string – sort of like a password, essentially crypt() is run against the string a few times, taking parts out and using them as salts for the next round. Eventually a seemingly random string is put out and added to the user’s name. Sometimes, a recognizable word could appear and that’s where the idea of the custom tripcode was born. Would it be possible, through brute force, to generate a “random” string of your choosing. The answer is yes since usually the only first 10 characters are used to generate the tripcode, and only a 10 digit code is produced.

Many posters that use imageboards BECAUSE they can stay anonymous do not like tripcode users, which causes some people to use them just to annoy others which causes them to be even more despised. This is the power of the Internet.

Early trippers

One of the first tripcode crackers I’m aware of was called 4brute, made in 2004. You can see immediately it’s super simple and straightforward and well – compared to modern trippers unoptimized. (Source: here)

Someone has already done a pretty good roundup of the various tripcode programs out there as of ~2009 and I don’t know how long this site will stay up but ten years isn’t bad, but if you’re interested in the history and some of the source code/binaries for these older programs, check out this site, just named “tripcode“. Pretty thorough site and details how to use a lot of the programs since half of them are in Japanese.

Modern tripcode cracking

It was once just a glint of hope in the eyes of tripcode crackers to one day see a GPU-accelerated cracking tool but eventually someone was mad enough to do it. The first such tool was MTY, a Japanese tool aimed at AMD cards. The more popular GPU-accelerated tripcode cracker, and subject of this article, was Meriken’s Tripcode Engine. It can use CUDA or OpenCL, though MTY is faster for OpenCL users. I have an NVIDIA card so I have always prefered Meriken’s. Older tripcode generators, even on the fastest CPUs struggled to generate more than 20-30 million hashes per second. A CUDA tripper? Well on my machine it’s more like 1 billion per second.

Compiling 4 year old software that was never maintained

In the past few months, I have been mostly focused on my studies in preparation for a hopeful career change into IT and have gradually stopped playing video games but I still have a powerful graphics card that’s not really doing much so why not put it to work? I have a nicely running Gentoo installation with the latest NVIDIA drivers and CUDA ready to go – should be no problem to download and build this right? Wrong, but it wasn’t too much to figure it all out.

The first error I ran into was the project includes its own version of the c++ boost library, 1.61.0, which isn’t ancient or anything. As of now the latest version in portage is 1.72. However we get an error when trying to build the project using boost:

/home/jordan/src/merikens-std/BoostPackages/boost_1_61_0/tools/build/src/build/feature.jam:494: in feature.validate-value-string from module feature
error: "none" is not a known value of feature <optimization>
error: legal values: "off" "speed" "space"

On first inspection, I thought I just needed to change line 494 in feature.jam to use the value of “off” instead of “none” but that really led to no results. After searching the message online, I found a suggestion to add “–ignore-site-config” to the b2 options. The build script has a line for B2_OPTIONS=”” so I added it and retried building.

Now boost is good to go, and we get to the first CUDA code and another error presents itself. Apparently CUDA will only work with gcc 8.x at the newest. I live life on the bleeding edge and I got cut here. Luckily, Gentoo has great support for switching gcc versions and handles symlinking everything for you very well. So after compiling an older version of gcc I had made CUDA happy for a short time.

Gentoo’s eselect managing multiple gcc versions

There was another error that involved a function _xgetbv() in UtilityFunctions.cpp being redefined incorrectly. This was due to a change in how gcc-8.3 handled whatever it is this function does. The code in the project defined this function like so:

static uint64_t _xgetbv(uint32_t xcr)

However, the compiler complained that it had previously been defined (in gcc’s own files) as accepting an unsigned int instead of uint32_t and also complained that we were calling it static when it had previously been extern. The type was also long long instead of uint64_t After changing (I don’t know that I’d call it correcting…), line 128 read:

extern long long int _xgetbv(unsigned int xcr)

The last thing that caused errors from gcc was a preprocessor directive that was referencing something that hadn’t yet been defined for OpenCL. I’m not using OpenCL so I just commented that line out in Main.cpp

Now, nvcc is complaining.

token ""__CUDACC_VER__ is no longer supported. Use __CUDACC_VER_MAJOR__, __CUDACC_VER_MINOR__, and __CUDACC_VER_BUILD__ instead.""

I’ve never written code for CUDA, but it looks like they’ve changed the way you define which version of CUDA you have from a single variable to 3 separate ones. I’m not proud of it, but the way around this for me was to just comment out the line in <cuda-installdir>/include/crt/common_functions.h that contained this message. At its core it’s an incompatibility with the version of boost Meriken’s Tripcode Engine is using and the modern CUDA library. I still get lots of warnings about the CUDA_VERSION being redefined (in the build script I manually set it to 10.2) but a warning’s just a warning.

There’s more errors about cuda arch support in CMakeLists.txt. Support for Fermi-based cards was dropped in CUDA 9 (current version is 10) but there was still lines about compute_20 in the file that nvcc hated so I just deleted the older architectures from the file and it moved on without complaint.

finally, it builds (with –disable-opencl)

100% finally

At this point I was expecting all the hacking about I did to cause it to crash or not work but it seems to work fine so far. Below, I’ll post the diffs so you can patch the source to build yourself but I’m not providing the diff for the cuda header because I wouldn’t want someone to break a system library. Just know it was line 74 in common_functions.h as mentioned above. The patches and a script to apply them are on my github. The source for the program itself can also be found on github, courtesy Meriken. For Windows users, binaries are provided that still work but as you can tell some work had to be done for Linux!

BuildAll.sh.patch

7c7
< B2_OPTIONS=""
---
> B2_OPTIONS="--ignore-site-config"
24c24
< 	CMAKE_OPTIONS=$'$CMAKE_OPTIONS -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_FLAGS=-stdlib=libc++'
---
> 	CMAKE_OPTIONS=$'$CMAKE_OPTIONS -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_FLAGS=-stdlib=libc++ -DCFLAGS=-stdlib=libc++ '

CMakeLists.txt.patch

115c115
< 	set(MTE_COMPILE_FLAGS "${MTE_COMPILE_FLAGS} -DENABLE_CUDA -DCUDA_VERSION=${CUDA_VERSION_MAJOR}${CUDA_VERSION_MINOR}")
---
> 	set(MTE_COMPILE_FLAGS "${MTE_COMPILE_FLAGS} -DENABLE_CUDA -DCUDA_VERSION=10.2")
297,298d296
<             -gencode=arch=compute_20,code=sm_20 
<             -gencode=arch=compute_20,code=sm_21 
306c304
< 	    set(CUDA_NVCC_FLAGS -DENABLE_CUDA;-gencode=arch=compute_20,code=sm_20;-gencode=arch=compute_20,code=sm_21;-gencode=arch=compute_30,code=sm_30;-gencode=arch=compute_32,code=sm_32;-gencode=arch=compute_35,code=sm_35;-gencode=arch=compute_37,code=sm_37;-gencode=arch=compute_50,code=sm_50;-gencode=arch=compute_52,code=sm_52;-gencode=arch=compute_53,code=sm_53;-gencode=arch=compute_60,code=sm_60;-gencode=arch=compute_61,code=sm_61;-gencode=arch=compute_61,code=compute_61)
---
> 	    set(CUDA_NVCC_FLAGS -DENABLE_CUDA;-gencode=arch=compute_30,code=sm_30;-gencode=arch=compute_32,code=sm_32;-gencode=arch=compute_35,code=sm_35;-gencode=arch=compute_37,code=sm_37;-gencode=arch=compute_50,code=sm_50;-gencode=arch=compute_52,code=sm_52;-gencode=arch=compute_53,code=sm_53;-gencode=arch=compute_60,code=sm_60;-gencode=arch=compute_61,code=sm_61;-gencode=arch=compute_61,code=compute_61)
308c306
< 	    set(CUDA_NVCC_FLAGS -DENABLE_CUDA;-gencode=arch=compute_20,code=sm_20;-gencode=arch=compute_20,code=sm_21;-gencode=arch=compute_30,code=sm_30;-gencode=arch=compute_32,code=sm_32;-gencode=arch=compute_35,code=sm_35;-gencode=arch=compute_37,code=sm_37;-gencode=arch=compute_50,code=sm_50;-gencode=arch=compute_52,code=sm_52;-gencode=arch=compute_53,code=sm_53;-gencode=arch=compute_53,code=compute_53)
---
> 	    set(CUDA_NVCC_FLAGS -DENABLE_CUDA;-gencode=arch=compute_30,code=sm_30;-gencode=arch=compute_32,code=sm_32;-gencode=arch=compute_35,code=sm_35;-gencode=arch=compute_37,code=sm_37;-gencode=arch=compute_50,code=sm_50;-gencode=arch=compute_52,code=sm_52;-gencode=arch=compute_53,code=sm_53;-gencode=arch=compute_53,code=compute_53)

Main.cpp.patch

879c879
< static std::queue<struct OpenCLDeviceSearchThreadInfo> deleted_opencl_device_search_thread_info_queue;
---
> // static std::queue<struct OpenCLDeviceSearchThreadInfo> deleted_opencl_device_search_thread_info_queue;

UtilityFunctions.cpp.patch

128c128
< static uint64_t _xgetbv(uint32_t xcr)
---
> extern long long int _xgetbv(unsigned int xcr)

And finally, a small script to apply the patches

patch.sh

#!/bin/bash
patch BuildAll.sh -i BuildAll.sh.patch
patch SourceFiles/CMakeLists.txt -i CMakeLists.txt.patch
patch SourceFiles/Main.cpp -i Main.cpp.patch
patch SourceFiles/UtilityFunctions.cpp -i UtilityFunctions.cpp.patch
Print Friendly, PDF & Email