# Initgriti Challenge Coin BSidesLV/DefCon 2023 I recently attended my first BSides Las Vegas/DefCon week across the pond. Throughout the second day of BSides, [Sarah](https://twitter.com/PolarToffee), [Ben](https://twitter.com/benmcga) and I decided to try our hands at solving the Intigriti challenge coin CTF, as it didn't appear to be a technology any of us had explored before. ## The Coin ![](https://hackmd.io/_uploads/HJqxM3kph.jpg) ## WayBack Machine Attempt [This](https://zhuanlan.zhihu.com/p/31196987) page appeared to reference a tool that could be used to decode WeChat Mini Programs located [here](https://github.com/yanke-guo/decode-wecode), however it returned a 404 on GitHub. Within the comments of the same blog, we were also able to locate someone hosting [their own version of the tool](https://laizutuan.com/tool/code) online. This tool also appeared to be captured on the WayBackMachine. ![](https://hackmd.io/_uploads/Bk4VsxT6h.png) Sadly, we were unable to extract a valid URL for the `DOWNLOAD QR CODE SCANNING TOOL ANDROID` button, and therefore we moved on to other leads. ## Final Solution If you're unfamiliar with the technology, it may appear to be some sort of QR code that needs unravelling into the traditional square form factor, this lead to us searching for variations of "circular QR code with lines". The above search prompted a variety of results within google images, including kik QR codes (which are similar, but not quite what we are looking for): ![kik QR code image](https://hackmd.io/_uploads/Hy1-QnkTn.png) Finally, the following image appeared, which closely resembles the print on the challenge coin: ![Weixin public doc image](https://hackmd.io/_uploads/By-I7n1p3.png) Essentially, the coin appears to be what's known as a Mini Program, which is a specific kind of scannable barcode developed and used by the Chinese messaging app "WeChat" (it also appears to be developed by the WeChat team, so we expected the majority of the documentation to originate from them). WeChat has been described as China's "app for everything", used for messaging, social media, and payments, launching Mini Programs as a kind of way for businesses to create integrations within the WeChat application. > In 2017, WeChat launched a feature called "Mini Programs" (小程序). A mini program is an app within an app. Business owners can create mini apps in the WeChat system, implemented using JavaScript plus a proprietary API. Users may install these inside the WeChat app. In January 2018, WeChat announced a record of 580,000 mini programs. With one Mini Program, consumers could scan the Quick Response (QR) code using their mobile phone at a supermarket counter and pay the bill through the user's WeChat mobile wallet. WeChat Games have received huge popularity, with its "Jump Jump" game attracting 400 million players in less than 3 days and attaining 100 million daily active users in just two weeks after its launch, as of January 2018. Ever since WeChat Mini Program's Launch, daily active user (DAU) of WeChat Mini Programs are increasing dramatically. In 2017, there was only 160 million DAU, however, the number reached 450 million at 2021. > >Source: Wikipedia The main issue we faced throughout this challenge was the inability to find reliable documentation, as the whole Mini Program functionality appears to be closed-source. Diving into decoding the program, and figuring out how to extract information from it was a matter of research, however, we tried a variety of approaches before turning to manual exploring. From [this](https://zhuanlan.zhihu.com/p/85164898) page, we obtained most of the important information required to solve the challenge. Such as the following: - According to [this](https://www.ifanr.com/minapp/904702) page, Mini Codes can be divided into 36, 54 or 72 lines. ![](https://hackmd.io/_uploads/B1T9yJ6ah.png) - This page also states that each line is divided up into 13 identifiable data points (with some corner lines as exceptions). - Most data is usually encrypted (however, for this challenge, we assumed it would be plain-text). - The data should be read starting from the inner-most valid point of data (known as the encoding region in the image below), to the outer-most valid data point of the same line. ![Legend of valid points](https://hackmd.io/_uploads/Bk4bARh6n.png) - For lines with no valid "encoding region" data points, simply skip the line and move to the next. - We start reading from the left-most line (9 o'clock on the 72 lined codes, for 36 it's the next one up going clock-wise). One more thing that should be noted, is that the 5 dots on the coin (central yellow dot, green dot in bottom right, and 3 black and white corner dots) can be ignored, as they are purely for aesthetic/placement guidance. With all the required information to decode the coin, we took a picture and attempted to make it as central as possible (attached above). This image was then modified by python to plot lines to guide the 13 different data points on the coin. ```python # Kudos to Sarah for the code import cv2 import numpy import matplotlib img = cv2.imread("coin.PNG", cv2.IMREAD_COLOR) size = img.shape img_center_x = round(size[0] / 2) img_center_y = round(size[1] / 2) - 30 radius = 320 for i in range(0,13): if i == 0 or i == 3 or i == 12: print("skipping") else: img = cv2.circle(img, (img_center_x,img_center_y), radius, (255,0,0), 3) radius += 32 cv2.imshow("image", img) cv2.imwrite("coin_lines_new_adjust.png", img) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://hackmd.io/_uploads/S1eY0okTh.jpg) We can immediately disqualify all of the inner most points, as they do not belong to the encoded region (we are only looking for the small grey dot values within the legend above; the inner-most dots are all green, and are part of the logo area). We can also remove all of the points on the 4th inner-most blue line we placed on the image, as they belong to the metadata portion of the information. All dots on the outer-most line can also be ignored, as they belong to the "edge patch". ![](https://hackmd.io/_uploads/S1INqbap2.jpg) From here, the rest of the work was manual. Starting from the inner-most valid data point, on the line next along from 9 o'clock, moving along the lines in clock-wise order (notice the coin is slightly rotated clock-wise in the image, and the lines are marginally off center, this is purely due to human error). When decoding the information, you may be required to go back and check the legend image, as there are certain lines that do not follow the standard pattern for valid and invalid data-points. Some examples of the abnormalities can be found below: ![](https://hackmd.io/_uploads/SJVCPypT2.png) ![](https://hackmd.io/_uploads/H1NAwy6p3.png) The coin should decode to the following, with the indented, darker areas being a 1, and the absence of an indentation being a 0. From the following portion of the coin, we can extract the start of the URL (remember, in the image below you should start from the bottom-most line, as this represents 9 o'clock on a 36 line code): ![](https://hackmd.io/_uploads/B1FRCWa62.png) `01001000010101000101010001010000` = `HTTP` ![](https://hackmd.io/_uploads/rJBFJG66h.png) ## Conclusion This challenge was a great opportunity to dive into a technology that is almost completely unknown, with the only documentation being provided by other hobbyists who have dedicated their free time to decoding the mini program scheme. It also provided an interesting topic of conversation with the Intigriti team who was present at DefCon/BSides Las Vegas; huge kudos to them for coming up with such a unique concept for a challenge coin. For any questions, please feel free to contact me on [Twitter](https://twitter.com/SecGus).