
This is my first time in Czechia. And I'm very excited to be here. And this is very punk presentation on a personal project. So the title is quite honest. I reversed an Android application to try to hack transaction handled by an NFC tag. So let's start. Okay, you need to know that when I am not in my room to try to hack stuff like everyone I like to go to live events, in particular musical events festival. And it's very common that you can spend two or three days and hour per day in a festival and this means that probably you move from a stage to another to follow your favorite artist and but you need to drink and
eat. And often you need to I mean I will say always you need to buy food and drink inside the festival. Now there are different way to buy the food and drinks [snorts] in 2026. My favorite one is using just a credit card because you just need to tap and you can have your food or item or whatever. But these kind of events are not designed in this way. They try to add friction and hidden cost for everything. So a very common approach is using token. Why token? Token because they try to hack your your mind, your brain. A token often doesn't cost 1 euros or 1 unit. A token cost 2 euros. In this way you forgot the real pricing
of item because you see the pricing of item in the festival are expressed or written in token, not in euros. And and now it's very common to find um application that manage tokens. So, not physical token, but application where you can buy the token with real money and use this fake money to buy items in the festival. Why the application? Well, the main reason probably is that they can had to um to reduce the line to the different stand food stands and drink stands. And also because in this way they can collect data about uh the user that enjoyed the festival. So, in this case it was quite basic. I had an NFC tag at the the festival
bracelet and there was an application. I have an Android phone and uh I buy I I use the uh mobile application to buy the token uh the credits. And then uh the credits are stored uh in in my my mobile phone or at least I can read uh on the uh mobile application um the number of token that I bought. And I tap my uh my phone on my NFC bracelet. I I can transfer, so I can write data, the number of credit, on my NFC bracelet. Then I just go to my beer stand because every I mean, the only thing that I wanted to a festival is a beer and [snorts] uh I tried to pay uh the vendor using my
bracelet. The the stand operator that has uh the same app or a similar app just maybe with a different back end. They tap the app on the on the on my bracelet. If I have enough credit, I can get my beer. Then, in this specific scenario at least, uh the vendor application send data to a cloud infrastructure. And why I know this? Because after that I paid uh my beer, uh even if I haven't tapped in my uh NFC tag on my mobile phone, I have seen the credits that my credits was synced or so updated um on on my mobile phone. So, this is the user experience, the workflow. You have a tag, an NFC tag, you have a
mobile app, and the operator have uh has another app to check your credit. If you have enough credit, you buy uh the item. Otherwise, you need to buy credit using the app and write them on the bracelet. Perfect. And this is the reward, the beer. I want to show you a meme because it was fun. Especially the fun part is is that one. But okay, sorry. How does it work? So, uh this project I mean um at this festival uh I installed this app and I was curious, especially because there was written that it could work offline. So, I said, "Okay, how how does it work?" This is a very common question that I have for everything that I use,
not just for hacking purpose. It's very common for me to ask, "Okay, but how does it work?" >> [snorts] >> And this is a very uh good starting point to try to understand stuff. Uh this presentation, this project is a sort of love letter to the infosec community because often, I mean, at least for me, the best project, the best reverse engineering projects are not really to try to hack stuff, but just to "Hey, let's try to understand how it work." So, low budget, just a laptop and a smartphone are enough because hacking is more fun if it's for everyone. No root phone. Why no root phone? Well, because I didn't want to invest but my personal
budget to buy a phone just for room to to root it and because rooting an Android phone in 2026 is very frustrating and annoying. Uh it's not so easy like uh 10 years ago. For for good reason probably, but and only local client reversing. I was not interested to investigate the API. I was interested to find bug in the back end. I was not interested to um to try to hack uh a cloud infrastructure. I was interested just to understand if I could hack uh or find vulnerabilities in the logic of the application because if it can work offline, I need to understand why it can work offline. What I used um I I used the uh
I mean well, what I had technically. I had an NFC tag uh an NXP 216. It's very common one. Um I I had the Android application that was a React based application. Uh and then uh the direct user experience that is very important in this case because I have had the opportunity to use this application in a real environment in the production environment. So, I saw how it work. Tools that I used. So, uh I used the open source tool and solution. One of the most common is the uh Android uh the back bridge because um it's help you to communicate with the um connecting the mobile phone to the laptop. You can easily dump
uh data, write data, and so and so, install application, debug application. I use the Hermes Deck. It's a reversing engineering tool for disassembling Hermes bundle. Uh later we will see what is an Hermes bundle. I use the Android Unpin her. It's This is just a tool to to make an APK file, so an Android application, debuggable. Of- often >> [clears throat] >> production application and for good reason that the debugger uh disable. But if you want to start to reverse Android application, it's recommended to enable or to enforce the debugger. Um Then I use the APK tool to reverse the Android application. This means that APK tool is just a tool to open the APK file. It's sort of a zip
file. Uh and you can start to reverse the code. So you have access to the Java class or the Android bundle that can be in JavaScript or, in this case, the Hermes one. Uh then there is a ABC tool that is another tool for disassembling and assembling Hermes bytecode. Uh the main difference between uh HB tool and Hermes Deck is that with with HB tool you can also reassemble the Hermes bundle, um often broken because just one byte change break the bundle, but you can try to reassemble it. Uh it's very helpful if you want just to change Boolean value because in that case the risk to break the bundle is low. And often the Boolean value are used to
manage the logic in an application. And then the NFC tag info and NFC tools, they are two Android application that you can install for free on your mobile phone to read uh the data on most common NFC tag. Okay, let's start from the NFC tag. So, we have two important uh uh I I mean we we have two uh uh product, we'll say, something. Uh two items. Uh one is the NFC tag, so a physical card, and one is the Android application. I was most interested, honestly, in NFC card that to understand how it's work because often it's quite common uh to find misconfiguration for um this uh IoT device. Uh so, let's see. This was
um This is just a sample, but this is what uh what I found by reading the NFC tag. We can see that the lock byte are on the default value. This means that there are there is no configuration. And this means that they are boring, good, because they are not used. Uh this uh uh doesn't increase the complexity for us. Then we have a the capability counter. This is very common. I mean, it's a very useful feature or um for for example, ticket. If you want to create a ticket for public transportation, you want to count the number uh of usage of uh of the same ticket. For example, if uh a ticket can have a
uh multiple um rights or whatever. Uh it can be very helpful. This is a counter. This means that you can increase, but not decrease it. Um Then on uh and the end of the uh at the end I mean, in the last uh row, we can find other configuration, other lock byte, not used, and the authentication. This is interesting because the NFC tag NXP uh NTAG210 something something, it's a family of three tags, uh support the authentication. How it's work? Well, uh it is a symmetric authentication. This means that uh um the password is uh safely stored in the NXP tag. Uh but when the reader want to authenticate, then the reader need to send a command
where the password is in clear. So, in in the ideal world, you can technically intercept the password if you have access to a reader that can authenticate. >> [snorts] >> It's also interesting that uh the authentication is not required for all the slot, but it's just required from the slot 40. And there is a reason why it's required from the for just for some slot. So, uh what we have here is that uh and there is the proof of brute force protection. So, uh the last uh row is about the brute force protection. This means that after seven attempts, uh every authentication will fail. And I have understood this too late just because I I have decided to not read the
documentation in time. Uh and so, I burned my NXP tag. Uh I have because I tried technically to brute force it. Uh [snorts] good lesson. Uh So, the the lesson here is uh read the documentation before start to reverse uh an NXP tag. Um but let's see now the data about the transaction. So, uh when uh um I was to uh the festival, I could buy item and I could pay I can cool at credits so token to my bracelets. The how they were stored were using transaction data in the memory of the chip. You can the application writes the token technically application write the transaction and it was written also the number of token.
And so what we have here that every transaction was 12 bytes. Three three are required for the coins the number of token. Four bytes are for the day time so when you both the token or use the tokens the pen if and five bytes in the middle are probably a sort of signature. So even if you buy the same or even if you load the right the same number of token at the same time stamp with a different time stamp you have a different signature. And this adds complexity because I cannot just maybe copy the token I need to also understand how if I can replicate the signature. And then we can see that there is a a
similar transaction data also in the read-only memory. Why the read-only memory? Well, the read-only memory is used just by the stand operator. When you buy the beer for example, they write on your bracelet the rest so how many token you have after that you bought the beer. And Sorry. I forgot. >> [snorts] >> And uh
One second. Better. Okay. And uh so customer and the standard operator seem to use the same transaction format. They have the token, there is a signature, and there is a timestamp. But the operator can write the um the transaction data in a memory partition in memory slots that the the normal customer cannot use. Why? Because the operator slots are protected by a password, and I need to authenticate to write in that memory. Okay. So, apparently the only difference is that the operator can write in a specific slot where the customer cannot write. Uh and but the transaction data the transaction format is is the same. So, cyberquits, which kind of attack could we try on this NFC tag?
Well, one can be break the transaction signature. If we can if we know how to replicate the signature, how we can We have a timestamp, we have number of token. If we can sign these two things, we can always write in our uh in the slots in the customer slots the number of token that we want to have. And this is for free, and we hacked the bracelet for sure. Uh or at least the logic behind this transaction application. Then we can try to guess the NFC tag password. Why this could be interesting? Well, not because I mean not because it's allow us to load or write all all token that we want like breaking the transaction signature, but
because we can maybe buy just 10 token, buy a beer, and then just remove the operator transaction data. In this way, we can restore our initial token. And with a small amount of token, we can reorder multiple item multiple times. This is why finding the NFC tag can be interesting because we can in this way delete the operator transaction. And then there is the transaction reply attack. It's the most common. If I cannot guess the NFC tag password and if I cannot find how the token and timestamp are signed, maybe I can just replicate a transaction data. So, I write 10 token on my bracelet and then I try to replicate this writing process multiple time.
Okay. Now, we have a three different approach to try to hack the transaction on this mobile application on this service. And the question is, okay, which kind can can work? How I can test them? And here I started to look more in details to the Android application. So, I started to reverse the Android application. Why? Well, because maybe we are lucky. We can find the password directly embedded in the Android application. And so, we don't need to understand how it is work. We can just use the string. >> [snorts] >> Um but which kind of Android application I found when I try to reverse it? Well, I found a Hermes-based Android application. What is Hermes? Hermes is a JavaScript engine
with a high-performance open source made by Facebook. And it allow you to create um uh uh React application that that are faster that are optimized for mobile phone. That makes sense because uh you don't want maybe to have uh if you are I mean if you are working on a mobile application uh especially for Android the ecosystem is so different is so complex that optimization is a requirement. So the enormous bundle is just a precompiled binary that contain optimized bytecode. So it is a just JavaScript obfuscated and optimized. But this means that uh if you try to read uh if try to open an in the an Android index bundle that is an enormous one you cannot
properly read it. It's a binary file and you need to start to reverse every bytecode. This add complexity. Um why have you not tried dynamic analysis for example? Why I I decided to go for uh static reverse um process? Well uh um I I technically I tried dynamic analysis. But I failed. Uh uh why I failed? Well there is a lesson also here for me. Uh if you want to try a new technique that you don't know well enough or if it is the first time that you try uh probably starting from a production application or production environment is not a good idea. I mean for production I mean that I I didn't know the source
code of this application. It was written by developers to be used in a uh in real life so uh it's definitely not the first step. Uh if I can recommend something is okay you want to try dynamic analysis on Android application and to reverse an Android application. In this case, we're using Frida gadgets, you can but start from uh the I mean uh very small basic application that you wrote so you can understand how it work. In this case, for example, for me it was not just difficult to try to use Frida gadget on uh not rooted phone but also debugging the reason why it didn't work was not easy because the there were too many
uh different scenario, too many possibilities why it was not working. >> [snorts] >> So, uh I decided to not invest too much time in in this because well, it was my free time. I was just Well, I wanted just to have fun when I was reversing Android application and decided to go with a static analysis, especially because my I mean, uh I was hoping to find honestly the password or at least some key interesting key embedded directly in the code. >> [gasps] >> So, let's start. Uh ADB device is a common to find the mobile phone connected to your laptop. Then, with Android Unpinner, I listed my packages, also the application is done on my mobile phone.
I found my uh application. I dumped it. Um using APK tool, I uh disassembled it to extract the bundle and technically to extract what was inside application. Initially, I didn't know that was an Hermes bundle. I expected I mean uh I was sure that was a React application because you can understand it from the user interface. Um but uh yeah. Then, uh after that uh I have found out that it was an Hermes bundle and started to disassemble it using ABC tool. In particular, because I was interested to to read better, to find the string, try to understand the logic. And also I use the ABC decompiler just because it provide a better outcome in my opinion. It
provide a sort of pseudo JavaScript code for for the Hermes bundle. It makes sense because technically um uh React is React based application are just an evolution of a JavaScript application. Uh it's uh and the pseudo code was better from human perspective to to to I mean, it was in my opinion easier to understand. So, these are the two tool that I used uh uh tool reverse the bundle. Uh one provide that was very interesting the string.json and uh so extracting strings, boolean value, and integer. And uh this feature is very interesting if there is a ton of client logic. Why? Because if the ABC tool is able to extract this string.json uh so you can easily find if there are
maybe interesting string, but in particular they are boolean value. This means that that you can change the boolean value in the string.json and then recompile the entire bundle. In this way the recompile should work and if there is a specific feature, for example, a pro feature that is enabled or disabled by a logic, you can easily enable it and reassemble the application. Uh then ABC decompiler that's provide me just a better output to read the Hermes bytecode that I can and I mean in this way I can also use LLM to read the pseudo code because the Hermes bytecode are I mean I haven't properly tested because there were there were too many lines but
Uh, just to be clear the output the pseudo code that JS file that is the Hermes reversed had 2.5 million lines. So the context was too big for an LLM at least one year two years ago. Okay, now that we have understood how what is an Hermes bundle and how we can decompile it the next step is okay, decompile the bundle and start to investigate the code. First attempt was okay, let's try to break the transaction signature because this is the best scenario if I can sign the token if I can sign any transaction I have technically free token without without the necessity to pay any any transaction because other scenario required that you buy at least the
initial token. So this was the function to um to sign the transaction data that I found in the Hermes bundle. This code was rewritten using Cloud code. What I mean I I launched the ABC decompiler against the um the Hermes bundle. Then I I got this giant pseudo code file. I started to read it. I mean, for read I mean steps for specific keywords. For example, password, signature, and so and so. I found the interesting function and then I used cloud code to rewrite them better uh in languages that I could understand easier. In this case, JavaScript just because yes, but in general I prefer Python, for example. Um but the function were quite basic, in my opinion. So, uh
this is the function to calculate the signature. We can see that it's required a number of token. It's required a timestamp, so when you uh bought the token, uh but it's required also a secret that is dynamically injected in the in the in the function. Then it can concatenate all the all the all the values, so the token, the timestamp, the secret. Uh it calculate the hash and return it. So, now we know how the five bytes work for the signature. This is how the application sign the the transaction data. But we don't have the secret because it is dynamically injected. >> [snorts] >> And apparently it's not it was not in uh in the in the Hermes code or in the
application code base. I was not able to find it. Um Uh this means that we cannot easily break the signature. In addition, you need to think that all these reversing um um project was made at home after the festival. And this means that I could not test all my theories. Theories, so if the idea was, "Oh, maybe I can intercept the traffic." I cannot because I was not to the festival, so I cannot really test it. Okay, so this approach could not work because we don't have the secret. Uh, let's try to guess the NFC tag password. I mean, let's try to check if it is embedded in the in the in the code in the application,
and it wasn't. Or I was not able to find it, but I'm quite sure that it wasn't. So, how the the application calculate generate the password for the NFC tag? Well, it is interesting because there is a unique formula, unique function for all the bracelet, but all the bracelet have uh have a different password. Why? Because it is generated using the UID that is unique for every bracelet. It is provided by NXP directly. Uh And uh the but and there is a secret again. So, this function work like the previous one. We have the UID, a data that we know. Uh, but then there is a secret that is dynamically injected in the function to calculate
the uh the NFC to generate and then use the NFC password. This means that also this time I cannot use I cannot find and or guess the NFC the the password. And uh Okay. So, what is the remaining attempt? It is the transaction replay attack. Well, this is very quite basic approach in general. So, you have an NFC tag, and you just try to replicate the data, so copy the data that you have in other slot and see if the reader consider the new data valid data. How you can prevent this kind of attack? Well, it depend. You can add logic where you want. You can add check in the back end in the reader.
Mhm. In general, it's the reader that should check if the data are replicated or not or valid or not. It's the NFC bracelet is very static object and I cannot do calculation or any sort of operation. Advanced operation or check. I'm sorry. So, um let's try to understand how the bracelet uh how the application um run checks on the bracelet uh data to prevent uh uh uh replay attack. So, um this is a big function that I tried to compress. Uh we can see that uh uh there are two check. One is for the operator's uh slots uh and one is for the user slot. The operator slot wearing read-only. We know this. They are protected by the
password. We cannot write uh the operator's slot. Uh we can just write the user slot and in this kind of slot we can try the replication attack. So, let's try to understand this factor. Um it's just say that uh if uh um the application read all the transaction in the user slot, check if there are duplicated timestamp. If there are uh duplicated timestamp, uh um the application just skip that transaction. So, just this block a replay attack in our case. Why? Because if we want to replay um I mean, we want to replicate a transaction data, we need to copy the token, the signature for sure, and the timestamp. Just copying this, this means that our
um copied data has the same same timestamp. So, one of the two transactions will be ignored by the application. And then there is also another check. A a check on the timestamp timestamp of the user slots and operator slots. Why? Well, this is >> [snorts] >> uh This is the logic of the application. This is where honestly I started to think more. So, uh if you buy 10 credits and you write on the bracelet and you go that then to uh buy um an item uh the um the vendor need to write the rest on your bracelet. That will be lower than your initial amount of credit. And the timestamp will be more recent. But,
after that, if you uh buy uh additional token and application and you write on the bracelet, the application need to sum the operator um slots to the new added token. And this is why there is a check on the operator timestamp. So, what was the check? Was this. If uh ignore all the transaction data that are older than the operator timestamp. If the transaction data are um equal or uh the timestamp of the user slot are equal um or higher than the operator timestamp, consider them and sum to the to the total credit. And this is how uh the application calculate the amount of token that the user have. So, uh, by summing the operator
slots to the user slots that are more recent than the operator's slot. Okay. But, why just minor and non-minor are equal? Let start with math. So, what we have here? Um, we have a problem. I mean, this means that the replication attack is possible, but not copying the credit by the I mean, the slot by the by the user, but by copying the slot by the operator. What happened there is that Okay, but what happen if I copy um, um, a transaction data written by the operator? For sure, uh, it will pass this check and also this. So, I cannot do a proper replication attack from the transaction data of the user try to replicate them, but I can do a
transaction replication attack copying the operator um, uh, operator transaction data from their slot to my own one because I can read them. The slot were in read-only mode. So, the password were necessary to write or delete the transaction data, but I could always read them and that makes sense because the application need to calculate the amount of of credit that I had. So, let's start to do some math. We have initial amount of token. We know that an item costs uh, Z and we know that X need to be higher than Z. And, what I try to understand it was Okay, I can optimize my replication attack using math and the answer was yes because the idea is that if you want to
buy the minimum number of token to I don't know a buy free a beer for the entire festival you just need to understand this formula that was okay, you just need to buy the number of token of one beer multiplied by two and adding one token to that. If you add this, you have a a divergent condition and this means that for the entire festival you can drink for free. So the magic formula in this specific application logic was due to that minor thing that was not minor equal was okay I'm just I can do a replication attack on the operator slot and now I need to find a condition to minimize the amount of token and the
divergent condition is the reason why you can drink for free just paying two beer plus one euro to a festival. Mitigation. How you can mitigate it? Well, there are different way. I again one of the condition about this project was in your the back end if you are controlling the back end you can check everything but if you want to mitigate this in the app there are again multiple way. My recommendation was this one at the equal and you solve the problem but also use different signature between operator and user slot can solve the problem. So in this case was just a logical issue just an equal forgotten that allow me to drink for free to a festival and thank
you that was the my home made project. I hope you have fun and I hope you like to DRINK BEER TOO. >> [applause]
>> ANY QUESTION? ANY QUESTION? NO? UH-HUH. SURE QUESTION. YEAH.
Um first off, great talk. Very, very um fun, I would say. Um unfortunately, my question's not so technical. I'm wondering what festival you went to that sort of spawned this. Sorry, can you repeat? Which which festival did you go to that sort of you have these uh I cannot disclose that. I'm sorry. Ah, too bad. >> I cannot disclose. Too bad.
Uh Little bit. Yeah. But good question. Yeah, thank thank you for a great talk. I would have question. This was about payment, and would this something of this apply also to access badges based on the NFC? Uh can you repeat the question? Sorry. Uh if this uh similar technique or the analysis or the process or the vulnerability can be found in the access badges uh using the NFC? Uh well, potentially yes, but you know, the NFC tag in this case was not vulnerable by design. The NFC tag was safe. I I tried to understand if I could try to exploit just the hardware, but then it there are no um well-known vulnerabilities for the NXP NTAG, for
example family. Uh the reason why uh I was able to hack transaction was a logical error in the application in the product itself not so in the NFC tag. So, my answer is yes, but not because then the NFC is is vulnerable, but maybe because the logic in the reader or in the back end or in the application is vulnerable. So, you can try to replicate, but it's custom every time. >> [music]
>> Thank you. Thank you.