[{"content":"No reverse engineering this time. Just some good news.\nqrew, my QR food ordering SaaS for restaurants, has been selected for Web Summit\u0026rsquo;s ALPHA Startup Program.\nWeb Summit is one of the world\u0026rsquo;s largest technology conferences, bringing together startups, investors, tech companies, and entrepreneurs. Last year, it gathered over 70,000 attendees from over 150 countries.\nALPHA is Web Summit\u0026rsquo;s programme for early-stage startups, offering visibility and opportunities to connect with investors and potential partners.\nMore than 22,000 startups applied across Web Summit\u0026rsquo;s startup programmes last year, and just over 2,700 were accepted. That\u0026rsquo;s roughly a 12% acceptance rate.\nA few months ago, qrew was just an idea I brought back from a trip to China, where QR ordering is simply how lunch works. Today it\u0026rsquo;s a product with a pilot program open to restaurants.\nI never imagined this could happen when I started building qrew. It\u0026rsquo;s crazy where a single idea can take you.\n🍙 If you\u0026rsquo;re a restaurant, apply to qrew\u0026rsquo;s pilot program at https://getqrew.com! It\u0026rsquo;s okay if you offer Hawaiian pizza, really.\n🫵 If you\u0026rsquo;re a builder, keep going!\n","permalink":"https://victorperez.tech/blog/qrew-websummit-alpha/","summary":"qrew, my QR food ordering SaaS for restaurants, has been selected for Web Summit\u0026rsquo;s ALPHA Startup Program.","title":"qrew selected for Web Summit's ALPHA Startup Program"},{"content":"qrew was selected for Web Summit\u0026rsquo;s ALPHA Startup Program. More than 22,000 startups applied across their programs, and just over 2,700 were accepted. I wrote about it on the blog.\nWeb Summit\u0026rsquo;s opening night at the Altice Arena in Lisbon.\n","permalink":"https://victorperez.tech/awards/websummit-alpha/","summary":"For qrew","title":"Selected for Web Summit's ALPHA Startup Program"},{"content":"As strange as it may sound, I\u0026rsquo;ve never attempted to tweak my iPhone. Last week, a friend casually told me that she had just installed a 定制V — dìngzhì V, a modified WeChat client on her iPhone.\nI couldn\u0026rsquo;t believe what I was hearing. She had bought a DIY guide and all the necessary cryptographic material from Taobao\u0026hellip; for 15 RMB ($2.2 USD) a year!\nAfter a week of investigating, it turns out renting Apple Developer account capacity to sideload your own apps is a lucrative business in China, where third-party tweaks for everyday apps are particularly popular among Gen Z users.\nOn Android, the process is relatively straightforward. On iOS, however, there\u0026rsquo;s a fascinating piece of infrastructure that has been automated and monetized, allowing large numbers of users (most of them non-technical!) to sideload apps that would otherwise never make it through the App Store.\nThis is the result of a week of deep investigation: certificate reading, app file unpacking and burning through translation apps\u0026rsquo; rate limits across the Chinese Internet. Today, I\u0026rsquo;m bringing you along as I figure out how everything works, using my friend\u0026rsquo;s real setup as a case study.\nWhat\u0026rsquo;s in the package? Upon buying, the seller will automatically DM you on Taobao with a link to instructions and a secret key (typically referred to as 卡密 — ka mi), such as SSBZ57CAE9E4A6C7 (actual key extracted from a video tutorial, not valid anymore).\nWhile the instructions also cover the PC workflow, I\u0026rsquo;ll focus exclusively on iOS, since that\u0026rsquo;s where things get interesting. Android sideloading is comparatively straightforward, so there is much less of a need for this kind of signing infrastructure.\nThe flow described in the document can be summarised as:\nVisit a vendor-controlled website and submit your UDID (your Apple Unique Device ID) together with the 卡密. The backend registers the device and generates a signed .ipa (iOS App Package) containing a self-signing app, typically 全能签 — quán néng qiān. Install the self-signing app on your iPhone. Use the self-signing app to sign a modified WeChat IPA (or, in principle, another IPA of your choice). Install the newly signed app on the iPhone. Notice what\u0026rsquo;s not being sold here: the modified WeChat IPA itself. The Taobao product is essentially a package of signing credentials and infrastructure that gets a signing tool onto your device. The application you ultimately want to install can come from somewhere else (though the seller may attach the modded WeChat IPA to the doc, as is the case with my friend\u0026rsquo;s guide).\nAt every stage of the process, iOS applies a different part of its code-signing and application-distribution machinery. None of this requires a jailbreak or an exploit: the vendors are essentially automating Apple\u0026rsquo;s own signing and provisioning mechanisms, then packaging the resulting workflow into something that can be purchased for a few yuan.\nThe result is a remarkably frictionless experience: from the user\u0026rsquo;s perspective, it is basically buy → enter UDID → install 全能签 → sign IPA → install.\nApple Sideloading 101 In order to understand the flow internals, you first need to understand how sideloading works on Apple platforms.\nSideloading means installing an app through a distribution mechanism other than the normal App Store flow. At a high level, it means obtaining an application package (an .apk on Android or an .ipa on iOS) and getting the operating system to install and execute it.\nCode signing allows the operating system to verify that the app it\u0026rsquo;s about to run has not been modified since it was signed, and that it was signed using a signing identity recognized by Apple. This applies to any app you\u0026rsquo;d want to upload to an app store, but particularly in iOS, code signing is enforced as well before running any app, regardless of its distribution channel.\nSo what makes an iOS app\u0026rsquo;s signature \u0026ldquo;valid\u0026rdquo;?\nWe\u0026rsquo;re going to skip all possible iOS app distribution methods and get straight to the one these vendors use: Ad Hoc distribution\nFor now, all you need to know is that we need three basic ingredients to make Ad Hoc sideloading happen:\nAn Apple-issued distribution certificate (.cer) containing the public key associated with the developer\u0026rsquo;s signing identity. The corresponding private key, which is used to cryptographically sign the application after it has been built. The certificate and the private key are commonly packaged together in a password-protected .p12 file. An Apple provisioning profile (.mobileprovision). Think of it as a whitelist that contains the device UDIDs authorized to run a certain app, along with Entitlements that define which privileged capabilities and configuration the signed app is authorized to use. For the rest of this article, I\u0026rsquo;m going to refer to these three elements as signing credentials.\nThe important distinction is that the private key performs the cryptographic signing, while the certificate establishes the signing identity associated with that signature.\nThe provisioning profile defines the distribution authorization and Entitlements that the signed application is allowed to use.\nI\u0026rsquo;ll go into more depth about the Ad Hoc provisioning model and the contents of each file later in the article. But so far, you\u0026rsquo;ve got everything you need to continue.\nInstalling the self-signing app (全能签) l Now that you know what it takes to sideload an app, you might be seeing a chicken-and-egg problem ahead: if we need a self-signing app to sideload apps, who signs the self-signing app so you can run it on your iPhone?\nThe answer is: the vendor has a backend that does it for you.\nThey register your UDID in their Apple Developer account, create an Ad Hoc provisioning profile containing your device, and use their signing identity to sign 全能签. Once 全能签 lands on your iPhone, the app can be used to sign and install other IPAs until the signing credentials or provisioning profile expire\u0026hellip; or Apple revokes your certificate.\nThis chicken-and-egg problem lies at the gate of iOS sideloading: if you can\u0026rsquo;t get a signed self-signing app onto your device, there is no convenient way to use that app to sign anything else.\nThere are several ways around this:\nSign your own self-signing app. There are several open-source implementations available, but you\u0026rsquo;ll still need your own Apple signing credentials and provisioning profile. Have someone else sign it for you. This is the route taken by the commercial services we\u0026rsquo;re looking at. Here you can see other services that do exactly the same thing: https://p12.ct12.com.cn/ https://sign.drnrt8.cn/sign/ In all of these websites, there\u0026rsquo;s a form prompting for the UDID and the 卡密 (kǎmì, essentially a redemption/access code). Interestingly, there\u0026rsquo;s always a text box saying that existing users don\u0026rsquo;t need to enter the 卡密 again.\nThe exact purpose of the 卡密 is not exposed by the frontend, but its behavior strongly suggests that it acts as a purchase or authorization token: on the first registration, the service associates the user\u0026rsquo;s UDID with the purchased service, while subsequent visits can identify the existing registration without requiring the code again.\nOnly 全能签\u0026rsquo;s official website gives you the additional option of bringing your own signing materials. You can provide a .p12 and its password together with a .mobileprovision, allowing the service to sign 全能签 using your own signing identity.\nFor our live experiment, we\u0026rsquo;ll use the website my friend\u0026rsquo;s vendor sent her: https://qdp12.letuip12.cn/\nThe website\u0026rsquo;s purpose, at a glance If we look back at the ingredients required to sideload an app — in this case, the self-signing app — you\u0026rsquo;ll remember that we need both a signing identity and a provisioning profile.\nThe .p12 contains the certificate and corresponding private key used to create the code signature. The .mobileprovision, on the other hand, tells iOS which application identifier, entitlements, and devices are authorized by that profile.\nSo, after receiving your UDID, the vendor can register your device in its Apple Developer account and generate an Ad Hoc provisioning profile containing that UDID. The vendor then uses the corresponding signing identity together with that provisioning profile to sign 全能签. In this case, the signing happens server-side.\nBack to the website, the form on screen gives you several options:\nDownload the signed 全能签 IPA file. Download the EasySign IPA file, a very similar self-signing app we won\u0026rsquo;t cover today. Download the certificates associated with the signing service. Check your subscription status. From here, you have two paths.\nIf you\u0026rsquo;d like to explore how the vendor obtains your UDID automatically, go to the \u0026ldquo;Obtaining the UDID with an Apple .mobileconfig file\u0026rdquo; subsection.\nIf you stay here, I\u0026rsquo;ll show you how the signing process works by opening the IPA file and inspecting its embedded .mobileprovision. By comparing the provisioning profile with the app\u0026rsquo;s bundle identifier and the device UDID, we can verify exactly how this installation was authorized. Let\u0026rsquo;s go.\nInspecting 全能签\u0026rsquo;s signature Clicking on 安装APP (install app) on the website redirects to a page with a download button, which points to:\nitms-services://?action=download-manifest\u0026amp;url=https%3A%2F%2Finstall.letuip12.cn%2FgetInstallPlist%2F1788948399862\nThat URL shows yet another cool piece of Apple tech: over-the-air (OTA) installs.\nWhen a developer wants to distribute their app (modded or not), Xcode gives them the option to \u0026ldquo;Include manifest for over-the-air installation\u0026rdquo;, if they\u0026rsquo;re planning to use Ad Hoc as a means of distribution. This is done so testers don\u0026rsquo;t have to ask for the IPA and install it themselves. Instead, the distribution is served by the developer, and Apple signing ensures the app can only be installed on authorized devices (= their UDIDs are in the .mobileprovision file).\nFor our vendor, this means users whose devices are registered (i.e. users who bought their services on Taobao) can have 全能签 installed right on their iPhones, in one click. Incredibly convenient.\nApple\u0026rsquo;s documentation is fairly obscure on this subject: OTA installs are detailedly documented in a section belonging to Apple Developer Enterprise Program, but the fact non-Enterprise Apple Developer Program members can also use it is implied in some forums and, officially, in minute 8:50 of WWDC19, session 304.\nI don\u0026rsquo;t have my MacBook within reach right now, but if we decode the url parameter of the itms-services link, we\u0026rsquo;ll be able to read it without using Safari:\n\u0026lt;!-- ############################################# --\u0026gt; \u0026lt;!-- # 1788717174.plist (app manifest file) # --\u0026gt; \u0026lt;!-- ############################################# --\u0026gt; \u0026lt;plist version=\u0026#34;1.0\u0026#34;\u0026gt; \u0026lt;dict\u0026gt; \u0026lt;key\u0026gt;items\u0026lt;/key\u0026gt; \u0026lt;array\u0026gt; \u0026lt;dict\u0026gt; \u0026lt;key\u0026gt;assets\u0026lt;/key\u0026gt; \u0026lt;array\u0026gt; \u0026lt;dict\u0026gt; \u0026lt;key\u0026gt;kind\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;software-package\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;url\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt; \u0026lt;![CDATA[ https://install.letuip12.cn/signed/\u0026lt;YOUR-UDID\u0026gt;_4SAS/\u0026lt;UNIX-EPOCH-MS\u0026gt;.ipa ]]\u0026gt; \u0026lt;/string\u0026gt; \u0026lt;/dict\u0026gt; \u0026lt;dict\u0026gt; \u0026lt;key\u0026gt;kind\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;display-image\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;needs-shine\u0026lt;/key\u0026gt; \u0026lt;integer\u0026gt;0\u0026lt;/integer\u0026gt; \u0026lt;key\u0026gt;url\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt; \u0026lt;![CDATA[ https://install.letuip12.cn/upload_file/2026-05-29/div9e3lt7vih9rl3jy.png ]]\u0026gt; \u0026lt;/string\u0026gt; \u0026lt;/dict\u0026gt; \u0026lt;dict\u0026gt; \u0026lt;key\u0026gt;kind\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;full-size-image\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;needs-shine\u0026lt;/key\u0026gt; \u0026lt;true/\u0026gt; \u0026lt;key\u0026gt;url\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt; \u0026lt;![CDATA[ https://install.letuip12.cn/upload_file/2026-05-29/div9e3lt7vih9rl3jy.png ]]\u0026gt; \u0026lt;/string\u0026gt; \u0026lt;/dict\u0026gt; \u0026lt;/array\u0026gt; \u0026lt;key\u0026gt;metadata\u0026lt;/key\u0026gt; \u0026lt;dict\u0026gt; \u0026lt;key\u0026gt;bundle-identifier\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;signall.nuosike.sign\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;bundle-version\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt; \u0026lt;![CDATA[ 27.0.9 ]]\u0026gt; \u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;kind\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;software\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;title\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt; \u0026lt;![CDATA[ 全能签_全功能 (1).ipa ]]\u0026gt; \u0026lt;/string\u0026gt; \u0026lt;/dict\u0026gt; \u0026lt;/dict\u0026gt; \u0026lt;/array\u0026gt; \u0026lt;/dict\u0026gt; \u0026lt;/plist\u0026gt; Gotcha! With this information, we can just GET the IPA file straight from the server regardless of our OS. An IPA is essentially a renamed ZIP archive, so let\u0026rsquo;s crack it open\u0026hellip;\nAnother provisioning file? Inside an iOS app bundle distributed this way, you\u0026rsquo;ll find an embedded.mobileprovision file. Try diffing both this and the original .mobileprovision the Taobao seller gives the buyer and you will find no difference. They\u0026rsquo;re exactly the same.\n\u0026lt;!-- ######################################################### --\u0026gt; \u0026lt;!-- # 描述文件.mobileprovision / embedded.mobileprovision # --\u0026gt; \u0026lt;!-- ######################################################### --\u0026gt; \u0026lt;!DOCTYPE plist PUBLIC \u0026#34;-//Apple//DTD PLIST 1.0//EN\u0026#34; \u0026#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd\u0026#34;\u0026gt; \u0026lt;plist version=\u0026#34;1.0\u0026#34;\u0026gt; \u0026lt;dict\u0026gt; \u0026lt;key\u0026gt;AppIDName\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;Moon9069Cancer2921 e4b375633df03d85d53c670880078144\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;ApplicationIdentifierPrefix\u0026lt;/key\u0026gt; \u0026lt;array\u0026gt; \u0026lt;string\u0026gt;U7W7BC53HF\u0026lt;/string\u0026gt; \u0026lt;/array\u0026gt; \u0026lt;key\u0026gt;CreationDate\u0026lt;/key\u0026gt; \u0026lt;date\u0026gt;2026-09-02T09:49:06Z\u0026lt;/date\u0026gt; \u0026lt;key\u0026gt;Platform\u0026lt;/key\u0026gt; \u0026lt;array\u0026gt; \u0026lt;string\u0026gt;iOS\u0026lt;/string\u0026gt; \u0026lt;string\u0026gt;xrOS\u0026lt;/string\u0026gt; \u0026lt;string\u0026gt;visionOS\u0026lt;/string\u0026gt; \u0026lt;/array\u0026gt; \u0026lt;key\u0026gt;IsXcodeManaged\u0026lt;/key\u0026gt; \u0026lt;false/\u0026gt; \u0026lt;key\u0026gt;DeveloperCertificates\u0026lt;/key\u0026gt; \u0026lt;array\u0026gt; \u0026lt;data\u0026gt;MIIFtTCCBJ2gA...\u0026lt;/data\u0026gt; \u0026lt;/array\u0026gt; \u0026lt;key\u0026gt;DER-Encoded-Profile\u0026lt;/key\u0026gt; \u0026lt;data\u0026gt;MIIWxgYJKoZIh...\u0026lt;/data\u0026gt; \u0026lt;key\u0026gt;Entitlements\u0026lt;/key\u0026gt; \u0026lt;dict\u0026gt; \u0026lt;key\u0026gt;com.apple.developer.system-extension.install\u0026lt;/key\u0026gt; \u0026lt;true/\u0026gt; \u0026lt;!-- Compacted for readability --\u0026gt; \u0026lt;key\u0026gt;application-identifier\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;U7W7BC53HF.app.moon9069.cancer2921\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;keychain-access-groups\u0026lt;/key\u0026gt; \u0026lt;array\u0026gt; \u0026lt;string\u0026gt;U7W7BC53HF.*\u0026lt;/string\u0026gt; \u0026lt;string\u0026gt;com.apple.token\u0026lt;/string\u0026gt; \u0026lt;/array\u0026gt; \u0026lt;key\u0026gt;com.apple.developer.team-identifier\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;U7W7BC53HF\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;com.apple.developer.kernel.increased-debugging-memory-limit\u0026lt;/key\u0026gt; \u0026lt;true/\u0026gt; \u0026lt;/dict\u0026gt; \u0026lt;key\u0026gt;ExpirationDate\u0026lt;/key\u0026gt; \u0026lt;date\u0026gt;2027-08-29T16:57:54Z\u0026lt;/date\u0026gt; \u0026lt;key\u0026gt;Name\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;YOUR_UDID\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;ProvisionedDevices\u0026lt;/key\u0026gt; \u0026lt;array\u0026gt; \u0026lt;string\u0026gt;YOUR_UDID\u0026lt;/string\u0026gt; \u0026lt;/array\u0026gt; \u0026lt;key\u0026gt;TeamIdentifier\u0026lt;/key\u0026gt; \u0026lt;array\u0026gt; \u0026lt;string\u0026gt;U7W7BC53HF\u0026lt;/string\u0026gt; \u0026lt;/array\u0026gt; \u0026lt;key\u0026gt;TeamName\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;Arnold Thomas\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;TimeToLive\u0026lt;/key\u0026gt; \u0026lt;integer\u0026gt;361\u0026lt;/integer\u0026gt; \u0026lt;key\u0026gt;UUID\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;114ada0f-9f29-4105-ac1e-dfef6233267e\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;Version\u0026lt;/key\u0026gt; \u0026lt;integer\u0026gt;1\u0026lt;/integer\u0026gt; \u0026lt;/dict\u0026gt; \u0026lt;/plist\u0026gt; There is some interesting metadata here. But the concept I\u0026rsquo;d like you to stick with is that the TeamIdentifier and certificate identity line up, and most importantly, the certificate\u0026rsquo;s validity period lines up with the profile\u0026rsquo;s ExpirationDate. Your UDID is there too.\nI promised before that I\u0026rsquo;d prove this vendor is using Ad Hoc provisioning. Apple\u0026rsquo;s documentation explicitly states that devices are associated with Development and Ad Hoc provisioning profiles, and that their UDIDs are listed under ProvisionedDevices. Combined with the distribution certificate and the OTA distribution workflow we just observed, this lets us identify the profile as Ad Hoc rather than Enterprise.\nWe can dig a little deeper because, if you remember, the website to download 全能签 gave you the possibility of downloading the certificate it created for you. This is because you can reuse these signing credentials to sign your other IPAs in the future.\nWhen you download the certificate, you will get:\n证书文件.p12, containing your certificate and your private key. 卡密.txt, which is the password to open the .p12 container. This vendor chose to use 1 as the password. Nice. 描述文件.mobileprovision Opening the certificate will give the following information:\nPrivate Keys Key #1: RSA — 2048 bits\nCertificate #1 Subject: undefined=U7W7BC53HF, CN=iPhone Distribution: Arnold Thomas (U7W7BC53HF), OU=U7W7BC53HF, O=Arnold Thomas, C=US Issuer: CN=Apple Worldwide Developer Relations Certification Authority, OU=G3, O=Apple Inc., C=US Serial: 1fdc2d3320cc8e107d083a341568e443 Not Before: Sat, 29 Aug 2026 16:57:55 GMT Not After: Sun, 29 Aug 2027 16:57:54 GMT Signature: sha256WithRSAEncryption\nCompare this data with what\u0026rsquo;s inside .mobileprovision. This tells us that the provisioning profile is tied to this Apple Developer identity and authorizes the device we\u0026rsquo;re installing on. The certificate\u0026rsquo;s validity period also lines up with the profile\u0026rsquo;s expiration date. The puzzle is complete!\nObtaining the UDID with an Apple .mobileconfig file The UDID is your Apple device\u0026rsquo;s unique identifier. It\u0026rsquo;s not a secret, but it\u0026rsquo;s not particularly easy to retrieve either. This identifier is commonly used for app development: developers can register a device\u0026rsquo;s UDID in their Apple Developer account, effectively associating that physical device with their development and distribution workflows.\nThe average user will never know that such an ID exists, and, to be frank, they don\u0026rsquo;t need to. The problem is that if they ever want to retrieve their iPhone\u0026rsquo;s UDID, they\u0026rsquo;ll typically need to use a Mac or rely on an external service.\nThe most interesting part of the websites used to install 全能签 is that they often have a button in their form to \u0026ldquo;obtain the UDID\u0026rdquo;. Clicking it downloads a .mobileconfig file, a special configuration profile that triggers a prompt on the iPhone\u0026rsquo;s Settings app. This type of profile can request device information and send the collected data to the vendor\u0026rsquo;s backend.\nLet\u0026rsquo;s open the file my friend got:\n\u0026lt;!-- #################################### --\u0026gt; \u0026lt;!-- # qdp12.letuip12.cn.mobileconfig # --\u0026gt; \u0026lt;!-- #################################### --\u0026gt; \u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;UTF-8\u0026#34;?\u0026gt; \u0026lt;!DOCTYPE plist PUBLIC \u0026#34;-//Apple//DTD PLIST 1.0//EN\u0026#34; \u0026#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd\u0026#34;\u0026gt; \u0026lt;plist version=\u0026#34;1.0\u0026#34;\u0026gt; \u0026lt;dict\u0026gt; \u0026lt;key\u0026gt;PayloadContent\u0026lt;/key\u0026gt; \u0026lt;dict\u0026gt; \u0026lt;key\u0026gt;URL\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;https://sign.drnrt8.cn/sign/UDID/sign-receive.php\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;DeviceAttributes\u0026lt;/key\u0026gt; \u0026lt;array\u0026gt; \u0026lt;string\u0026gt;UDID\u0026lt;/string\u0026gt; \u0026lt;string\u0026gt;IMEI\u0026lt;/string\u0026gt; \u0026lt;string\u0026gt;ICCID\u0026lt;/string\u0026gt; \u0026lt;string\u0026gt;VERSION\u0026lt;/string\u0026gt; \u0026lt;string\u0026gt;PRODUCT\u0026lt;/string\u0026gt; \u0026lt;/array\u0026gt; \u0026lt;/dict\u0026gt; \u0026lt;key\u0026gt;PayloadOrganization\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;UDID获取\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;PayloadDisplayName\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;全能签客户端\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;PayloadVersion\u0026lt;/key\u0026gt; \u0026lt;integer\u0026gt;1\u0026lt;/integer\u0026gt; \u0026lt;key\u0026gt;PayloadUUID\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;3C4DC7D2-E475-3375-489C-0BB8D456A653\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;PayloadIdentifier\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;全能签UDID获取\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;PayloadDescription\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;本描述文件仅用来获取设备UDID\u0026lt;/string\u0026gt; \u0026lt;key\u0026gt;PayloadType\u0026lt;/key\u0026gt; \u0026lt;string\u0026gt;Profile Service\u0026lt;/string\u0026gt; \u0026lt;/dict\u0026gt; \u0026lt;/plist\u0026gt; What you\u0026rsquo;re seeing is PLIST (Property List) syntax. Apple extensively uses it to store app-related configuration and metadata. Think of it as a structured file containing key-value pairs, similar to a JSON file. Plists can be stored in either XML or Apple\u0026rsquo;s binary format.\nInstalling the profile causes the specified device attributes to be sent to a third-party endpoint controlled by the signing service. The UDID is technically sufficient for the service to identify and register the device for Ad Hoc distribution.\nWhy the service additionally requests IMEI, ICCID, iOS version, and product information is unclear from the profile itself. Turns out, all .mobileconfig files I\u0026rsquo;ve examined request the exact same information, but send it to different endpoints. Interesting.\nI don\u0026rsquo;t know about the purpose of gathering this extra data from the evidence alone, but a quick look at Apple\u0026rsquo;s docs on registering devices in bulk shows that IMEI, ICCID and the rest of attributes .mobileconfig captures can be saved along the UDID for device management purposes.\nHow does 全能签 actually sign your apps? Hooray! We finally have 全能签 installed! From now on, the vendor\u0026rsquo;s job is done and we own the signing process.\nThe videos in the Feishu guide detail the next steps. At a glance, the process looks like:\nYou import your certificate into the app. If you remember, there was an option in the website to download the certificate the vendor used to sign 全能签. This is what we\u0026rsquo;ll use as well to sign our own apps. You import an IPA of your choice into the app. In this case, WeChat. The vendor added the app to the guide, but you can visit any repository, such as iPA资源站, and download any mod of your choice (at your own risk). Install the app! I don\u0026rsquo;t have access to 全能签 on my device, but I will walk you through the evidence I was able to gather from observing the app. This should give you sufficient insight into how self-signing apps typically work.\nBy definition, re-signing means replacing the existing code signature with a new one, so the app can be accepted by iOS.\nWhen we modify an IPA file, let\u0026rsquo;s say from Tencent, we are free to modify its contents (including its .mobileprovision), but any change to signed code or other signed content will invalidate the existing signature. However, iOS won\u0026rsquo;t accept installing or running that mod straight away without a valid code signature, which can be either a new Tencent signature (which obviously won\u0026rsquo;t happen)\u0026hellip; or yours.\n全能签 is a closed source app, so we don\u0026rsquo;t have much information about how the re-signing process occurs. However, we can infer how it works from the definition above and the app\u0026rsquo;s own output logs:\n全能签 · V7.7.1 创建缓存文件夹 [Create cache folder] 复制文件 [Copy file]: YOUR_APP.app 读取证书信息 [Read certificate info]: Apple Distribution: Dongguan Huicheng Information Technology Co., Ltd. (WS5V8952WK) 修改版本限制为 [Modify version restriction to]: iOS 10.0 移除设备限制 [Remove device restrictions] 开启文件访问 [Enable file access] 开始签名 [Start signing]: YOUR_IPA_NAME.ipa 签名成功 [Signing successful] 开始打包 [Start packaging]: YOUR_IPA_NAME.ipa 打包成功 [Packaging successful]: YOUR_IPA_NAME.ipa Fortunately, since code signing is a standard Apple mechanism, we can find open source automations on the Internet. Let\u0026rsquo;s take a look at this script from Daniel Torrecillas, an American developer:\n$ ./resign-ios-app \u0026#39;AnApp.ipa\u0026#39; \u0026#39;XC_iOS_comcompanyAnApp.mobileprovision\u0026#39; \u0026#39;iPhone Distribution: AnOrganization\u0026#39; Unzipping \u0026#34;AnApp.ipa\u0026#34;... Extracting .app... Removing existing _CodeSignature... Decoding \u0026#34;XC_iOS_comcompanyAnApp.mobileprovision\u0026#34; and writing to ProvisioningProfile.plist... Extracting \u0026#34;Entitlements\u0026#34; from ProvisioningProfile.plist and writing to Entitlements.plist... Embedding \u0026#34;XC_iOS_comcompanyAnApp.mobileprovision\u0026#34; into \u0026#34;AnApp.app\u0026#34;... Resigning \u0026#34;AnApp.app\u0026#34; with existing bundle identifier \u0026#34;com.company.AnApp\u0026#34; Resigning embedded Swift libraries... ./libswiftCoreImage.dylib: replacing existing signature ./libswiftObjectiveC.dylib: replacing existing signature # COMPACTED FOR READABILITY... Resigning embedded frameworks... ./BarcodeScanner.framework: replacing existing signature ./SQLite.framework: replacing existing signature Resigning \u0026#34;AnApp.app\u0026#34; with certificate \u0026#34;iPhone Distribution: AnOrganization\u0026#34;... Payload/AnApp.app: replacing existing signature Zipping app data into an .ipa... Resigning successful. Resigned app to /Users/daniel/resign-ios-app/resigned.ipa At a glance, you can see they both modify the files within the IPA. The main difference is that 全能签 hides most of the intermediate work behind its cache. The steps involving file access and removing restrictions in 全能签 may correspond to some of the processing we can see explicitly in the script, such as unpacking the IPA and handling the provisioning profile, but we can\u0026rsquo;t know exactly what they do from the logs alone. Finally, both resign the embedded code and the app itself, but 全能签 keeps the output much simpler.\nFinal word: the sky is the limit By this time, my friend has her modified WeChat client running on her iPhone. She\u0026rsquo;s been using it for a while now and are happy with it.\nPerhaps she\u0026rsquo;ll be okay with installing just one app and forgetting about this long process, but chances are she\u0026rsquo;ll find herself in one of the following situations: how can the app be updated? What if she wants to just try a modded client but still keep the original, Tencent-signed package in case anything goes wrong?\nNow that we\u0026rsquo;ve learnt the engineering behind the whole process, a new door opens: modding the mod.\nWe learned that we could re-sign essentially any IPA as long as we provide a valid signing identity and provisioning profile. And since we are the owners of the process, signing apps like 全能签 allow (and encourage) you to modify the mod\u0026rsquo;s bundle ID. The reason is simple and OS-agnostic: two apps with the same bundle ID can\u0026rsquo;t coexist as separate installations on the same device.\nBy changing the bundle ID, we could technically have com.tencent.xin, WeChat\u0026rsquo;s original bundle ID; but also a modded WeChat client called com.tencent.wx, or even com.tencent.wx.1. This gives the user multiple instances of the app on the same device, potentially allowing multiple accounts. Or even the ability to juggle between modded clients, each with a different set of in-app feature flags.\nOf course, and as you may expect, this goes directly against the T\u0026amp;Cs of many modern apps. Tech evolves fast, and tech companies race against the modding community, banning, patching and securing their apps, battling the desire of a whole generation to stand out and go above and beyond to express their individuality even on the smallest of UI details. Many people buy these certificates on Taobao without knowing the power they hold. You now do.\n","permalink":"https://victorperez.tech/blog/china-ios-app-modding/","summary":"How renting Apple Developer account capacity to sideload apps became a lucrative business in China, and how vendors automate Apple\u0026rsquo;s own signing infrastructure.","title":"A Technical Dive into China's iOS App Modding Economy"},{"content":"In February 2026 I spent 17 days in China. One of the things that stuck with me was how Meituan and Weixin handle food ordering. You sit down, scan a QR code on the table, and order directly from your phone. No waiting for a waiter to take your order, no paper menus, no friction. It just works, and it works everywhere.\nI came back to Spain thinking two things: those two giants have conditions and an ecosystem that nobody else can replicate, but the core idea is simple enough that I could build a version of it. And I happened to have a good excuse to try, since I was going through a selection process at Supabase at the time and wanted to build something real with the product rather than a toy demo.\nSo I did.\nqrew is a SaaS platform where restaurants get their own digital menu and ordering system. Customers scan a QR code on the table, browse the menu, and place their order from their phone. No app to install, no account to create. The kitchen gets the order in real time.\nThe guest flow, start to finish: browse the menu, choose a dish, review the order, and track it live.\nThe core runs on Supabase. Each restaurant is isolated with Row Level Security, so no customer or restaurant can ever touch another\u0026rsquo;s data. Orders flow through Realtime subscriptions so the kitchen display updates the moment a table submits. Edge Functions handle the business logic that shouldn\u0026rsquo;t live on the client.\nThe URL architecture uses capability URLs with JWT and RBAC: the QR code on each table encodes a short-lived signed token that grants scoped access to that specific restaurant and table. Customers get a frictionless experience without authentication, and restaurants get proper access control without managing user accounts.\nThe kitchen dashboard — every table\u0026rsquo;s orders, updating in real time.\nThe frontend is React.\nqrew was selected for Web Summit\u0026rsquo;s ALPHA Startup Program — I wrote about it over on the blog.\nqrew is live at getqrew.com, and I\u0026rsquo;m accepting testers. If you run a restaurant, give it a try. I\u0026rsquo;m building this in public at @vpx_tech.\nThe menu manager, where staff update dishes, prices, and availability from any browser.\n","permalink":"https://victorperez.tech/projects/qrew/","summary":"qrew is a full-stack SaaS for restaurants. Customers scan a QR code, order from their phone, and the kitchen gets it instantly.","title":"qrew"},{"content":"I was staying at an Airbnb. The host used a smart lock with a shared access system: you receive a URL with a time-limited token that refreshes during your stay and expires when you check out. You open the link on your phone, and there is an unlock button. Clean, modern, convenient.\nThe lock had a geofencing feature. The idea is that the button only works when you are physically near the property. If you wander too far, you cannot unlock remotely. This makes sense as a security boundary: the token might be shared, forwarded, or intercepted, but at least the attacker would need to be on-site to use it.\nI opened the link on my laptop instead of my phone and looked at the source.\nThe geolocation check runs entirely in the browser. When you are outside the defined radius, the app sets a CSS disabled attribute on the unlock button. That is the entire enforcement mechanism. The button is hidden. The API endpoint that triggers the unlock has no server-side location validation whatsoever.\nRemove the disabled attribute in DevTools. Click the button. The door opens.\nThe token is valid. The API accepts the request without checking where it came from. You could be sitting in a different country.\nI have reported this through the manufacturer\u0026rsquo;s responsible disclosure channels. Disclosure pending their response.\n","permalink":"https://victorperez.tech/security/smart-lock/","summary":"The smart lock on my Airbnb had a geofencing feature to prevent remote access. It only worked in CSS.","title":"I Could Unlock My Airbnb From Anywhere in the World"},{"content":"I have been building qrew, a QR table ordering platform and security has been on my mind throughout. The AI tools I use while coding are great at writing features but terrible at thinking about what could go wrong. So I do that part myself.\nOne concern I kept coming back to: what stops someone from grabbing the URL behind a QR code and using it from home? I switched to UUIDs in my own app early on, but at some point I ran out of ideas and decided to test a production system instead. If I could find a real attack surface in a live product, I would know exactly what to harden in mine.\nI have a favorite sushi place in Barcelona. One of the very few restaurants in the city that uses QR ordering. The problem was that I did not have a photo of their QR code handy.\nGoogle Maps reviewers did.\nA bit of scrolling, a screenshot, perspective correction, sharpness adjustment, and I had a clean scannable code. I scanned it from my apartment\u0026hellip; and it worked!\nThe session loaded with the restaurant\u0026rsquo;s full menu, the current order for that table, the total price, how many people were seated, and a button to add more food. I had full access to a live table session without being anywhere near the restaurant.\nThen I looked at the URL. The table identifier was not a UUID. It was a long sequential decimal number. I adjusted the last few digits and landed on a second active table. From there the pattern was obvious:\nf(t) = large_constant - table_index Every table in the restaurant, accessible from anywhere, in real time!\nAt scale, this is not just a curiosity. You could extract a business\u0026rsquo;s full consumer patterns from your pocket: how many people are dining, what they are ordering, when they order, how much they spend. Or you could just send surprise dishes to every table, which would be funny until it wasn\u0026rsquo;t.\nI contacted the provider\u0026rsquo;s security team through their authorized channels the same day. Needless to say, I didn\u0026rsquo;t interact with or modify any other customer\u0026rsquo;s live session.\n","permalink":"https://victorperez.tech/security/idor/","summary":"While building my own QR ordering app I decided to test a real production system. A Google Maps photo, some perspective correction, and I had live orders for every table.","title":"I Hacked My Favorite Sushi Restaurant Using Google Maps"},{"content":"RevenueCat (YC S18) is the leading subscription platform for mobile apps, trusted by over 50,000 apps including OpenAI, VSCO, and Notion. It powers in-app purchases and subscriptions for developers and enterprises worldwide.\nAs a Technical Account Manager, I supported more than twenty high-value enterprise customers including Runna, FC Barcelona, and Naver Corp, partnering closely with Customer Success and Product teams to deliver tailored solutions across implementation, optimization, and best practices.\nPart of my ramp involved owning a technical support queue for enterprise customers, managing complex integration cases under strict SLAs. Most of our communication happened asynchronously via Slack workflows, with occasional deep-dive sessions over Zoom for complex issues. I used Zendesk daily for ticket management and Linear for bug tracking and escalation.\nBeyond that, I contributed directly to our backend infrastructure by automating the premium support ticket assignment system, improving routing efficiency across the team. I also created sample apps and implemented our SDK to demonstrate integration patterns and reproduce customer issues in real-world scenarios.\n","permalink":"https://victorperez.tech/experience/revenuecat/","summary":"Enterprise Technical Account Manager. App monetisation, solution implementation and SDK support.","title":"RevenueCat"},{"content":"In the spring of 2024, my then salesman colleague “sold” me an OrangePi: a Chinese Raspberry Pi clone for a third of the price. After he spent two weeks showing off his Home Assistant setup, I decided it was time to get my hands on one, and after a long wait, it was finally home.\nI spent a reasonable amount of time setting it up, flashing different Linux distros, running a Minecraft server, and even managing to corrupt both the SD card and the hard drive. After a few months, it was time for the actual fun.\nThe thing is, I love sneakers, but being a size 15 makes it difficult to find them in retail stores. Luckily, Zalando Lounge, a German online fashion discount store, has hundreds of them.\nThe store works in a similar way to product drops. A few times, I found myself losing a product at a bargain price to bots, until I’d had enough: I was going to create my own. Hellasteez1 was born.\nThe architecture was entirely dockerized. I used Docker Swarm to spawn containers at will, a Node.js Express server that acted as the command center and frontend, a Selenium Grid container that performed the login to get a session cookie, and some auxiliary Python scripts to manage the cookie and process the information, which ended up in my self-hosted MongoDB instance.\nThis was incredibly fun to build, and I learnt a lot. However, debugging was slow and the risk of getting banned or facing API changes was real. In the end, I managed to automatically add a product to my cart, which was a huge win, but there were associated challenges (especially automated payment) that made the project too complex to be worth continuing.\nIf you\u0026rsquo;re curious, I came up with the name from one of my favorite songs by Skepta: \u0026ldquo;Sitting in front row seats at Louis V with hella steez.\u0026rdquo;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"https://victorperez.tech/projects/zalando-scraper/","summary":"I love sneakers. I love servers. Let\u0026rsquo;s have a server get me sneakers.","title":"Hellasteez"},{"content":" ❮ ❯ Living in Barcelona means there’s always something to do. With good weather, amazing food, deep history, and timeless architecture, no two plans ever feel the same… at least if you know where to go. For those who’ve run out of ideas, there was TopFirstDates.\nOriginally conceived as a simple plan-sharing app, the project quickly evolved into something else. I pivoted the concept when I realized there was nothing quite like it in the market (and, honestly, because topfirstdates.com sounded too good for SEO to pass up).\nThe app was one of my most ambitious projects at the time. I worked with Firebase Auth for user management, built a backend in PHP, used AWS RDS for relational data storage, and gave Kotlin Flows a try for reactive programming. One particularly fun challenge was figuring out how to “hack” Instagram URLs to embed previews directly inside the app — something their API didn’t officially support.\nThe concept was simple but charming: users could create and share \u0026ldquo;date itineraries\u0026rdquo; as curated lists of steps. For example, starting at a cozy café (with an embedded post or map location), then moving on to a landmark with a short description or a reel. Other users could follow their favorite creators, discover new plans in their feed, and save their favorite date ideas for later.\nIn the end, the app looked great and worked well, but it completely flopped in terms of marketing. Still, it was an incredible playground for experimenting with backend integration, media embedding, and user experience design. Maybe one day I’ll bring it back.\n","permalink":"https://victorperez.tech/projects/topfirstdates/","summary":"Share date ideas with the world.","title":"TopFirstDates"},{"content":"\nAfter winning AppsUP 2021, I rebuilt Clover from the ground up, adding Huawei Watch support. That earned me a Honorable Mention the following year.\n","permalink":"https://victorperez.tech/awards/clover-appsup22/","summary":"For Clover","title":"Huawei AppsUP 2022: Honorable Mention"},{"content":"\nPicture this: you\u0026rsquo;re a fresh graduate against big studios and uncertainly more experienced developers than you. An European app building competition. You need a chance to win, and conceive an app purposefuly for the hackathon. What\u0026rsquo;s your idea?\nI went for something the organising company would potentially release themselves, but somehow hasn\u0026rsquo;t been yet: enter CYAN, a Google Alerts-like app where you could get notified about what interests you the most, built natively with Huawei\u0026rsquo;s APIs.\n","permalink":"https://victorperez.tech/awards/cyan-appsup22/","summary":"For CYAN","title":"Huawei AppsUP 2022: Honorable Mention"},{"content":" ❮ ❯ When I think about my most successful project, I think of Clover.\nIt was my submission to a student hackathon organized by Huawei in 2020, which I won. I had two weeks to prototype an app that used Huawei APIs, and it looked like this:\nWanting to drift away from Android’s pre-built Material libraries, I designed the entire interface myself, excluding the character and the buttons, which were taken from a free asset database. I dug into Animatable to make the character walk and bob, and learned all things AlarmManager to set up notifications for treatments.\nThe Huawei APIs I used were:\nAwareness Kit: to detect changes in the weather and customize the entire app UI. Map and Site Kit: to integrate with Petal Maps and find nearby pharmacies, with the ability to call them directly from the app. ML Kit: to detect text in medication boxes and automatically fill out the data. I briefly integrated Ad Kit, but the ad quality wasn’t great, so I quickly took it out. After winning my first two awards, I redesigned the app from scratch and translated it into Kotlin. I used MVVM to separate concerns and reengineered the notification queue, which was by far the most complex feature in the app.\nLater in 2021, I created Clover for Watch, a Huawei Watch app that enabled users to dismiss treatments directly from their wrist. This earned me an Honorable Mention in AppsUP 2022.\nThe app had potential and was briefly available on the Google Play Store, although for most of its lifetime it was exclusively available on AppGallery, Huawei’s own app store. Poor marketing and the increasing cost of development eventually made me abandon the project, which became too big for a single person to maintain part-time.\nI’m satisfied, though: Apple only figured out the potential of this kind of app a year later, when iOS 16 was released.\n","permalink":"https://victorperez.tech/projects/clover/","summary":"Award-winning pill reminder for senior citizens. Designed for the Huawei ecosystem.","title":"Clover"},{"content":" ❮ ❯ This was my submission to the AppsUP 2022 competition, created in record time and conceived exclusively for the contest.\nTake Google Alerts, use Huawei\u0026rsquo;s Search Kit to fetch news, authenticate users with Huawei Account Kit and save their preferences in Huawei Cloud\u0026rsquo;s Object Storage Service. What you get is CYAN, an app that notifies users whenever new content appears online about the topics that interest them most.\nThis was a cool concept to explore, not only because Google Alerts doesn’t have a dedicated app, but also because it has received mixed opinions over time, leaving plenty of room for improvement. It also gave me a chance to dive deeper into more advanced topics such as user authentication and cloud object storage, effectively making it my first Internet-connected app.\n","permalink":"https://victorperez.tech/projects/cyan/","summary":"Award-winning Google Alerts equivalent for the Huawei ecosystem.","title":"CYAN"},{"content":" ❮ ❯ In the summer of 2021 I felt confident enough in Java to switch to the new standard: Kotlin. After reading some docs and watching a bunch of videos, I decided I wouldn\u0026rsquo;t remember anything unless I actually built a dummy project. This was it.\nAs simple as it sounds, I used Retrofit for the first time to connect to a video game API and display the results in an appealing way. I also implemented some basic state handling to filter and bookmark favorite titles, and used Jackson to persist the user\u0026rsquo;s selection.\n","permalink":"https://victorperez.tech/projects/gamesdatabase/","summary":"My first Kotlin and Retrofit project. Discover and save new favorite free games.","title":"Free-to-Play Games Database"},{"content":"New Relic, formerly listed on the NYSE (NEWR), is a global leader in observability helping organizations monitor, debug, and improve their software.\nBefore joining RevenueCat, I worked at New Relic as a Solutions Consultant. Depending on the week, I might be deep in architecture conversations with customers or helping the sales team close a new deal. It was a mix of technical strategy and relationship building that kept things interesting every single day.\nI partnered closely with Customer Advocates and Account Executives, owning the technical side of conversations with engineers, managers, and executive stakeholders. I enjoyed helping teams see how observability connected to their business goals and showing them practical ways to instrument their systems more effectively.\nWorking alongside some incredibly talented Account Executives, I helped teams exceed their annual revenue targets by more than one million dollars. I also supported three colleagues who achieved Presidents’ Club recognition for their results. I was often the person bridging the gap between technical detail and business value, translating complex implementation plans into outcomes that made sense to everyone.\nTo keep those relationships strong, I built Customer Business Reviews and Mutual Action Plans that documented milestones and progress throughout the customer journey. Everything was logged in Salesforce, and I used Gong and Clari to analyze calls and improve forecasting accuracy.\nOutside of my day-to-day work, I joined the Mobile SMEs group, where I helped other teams with mobile observability topics and contributed to launching the New Relic Certification Program. I also built the first iPhone observability showcase for the platform: some customers were asking about device-level instrumentation beyond the Mac infrastructure agent, so I used the New Relic Metric API and iOS Shortcuts to instrument my own phone. Nobody had done it before.\n","permalink":"https://victorperez.tech/experience/newrelic/","summary":"Solutions Consultant. Pre-sales, observability, and custom telemetry ingestion systems.","title":"New Relic"},{"content":"This was my first proper web project while I was learning JavaScript. The idea was simple: fetch data from a public API and plot it on an interactive map. However, it quickly turned into a great exercise in understanding state management and asynchronous logic in vanilla JS. Handling multiple requests, managing loading states, and updating the DOM efficiently without any frameworks gave me a solid foundation for what React and other libraries automate today.\nFor deployment, I experimented with different AWS services. I started with Lightsail for its simplicity, then moved to EC2 to get more control over the environment. I configured a basic Node.js web server, set up security groups, mapped a static IP through Elastic IP, and connected the domain using Route 53. Along the way, I learned how Virtual Private Clouds, DNS routing, and instance permissions fit together to deliver a public-facing web app.\nIt was a small project in scope but a huge leap in understanding how front-end logic and cloud infrastructure connect.\n","permalink":"https://victorperez.tech/projects/stations/","summary":"Web app to find cheap gas stations in Spain using Leaflet and a government API.","title":"todogasolineras.net"},{"content":"\nI live in Barcelona and I spend a lot of time walking around the Port Vell marina. It started as a way to unwind, but eventually the ships took hold of me. What are they carrying? Where are they going? I started using MarineTraffic obsessively.\nThat curiosity was actually what sparked YPSILON, my first serious piece of software: a yacht recommendation system I built as a student after one of those marina walks. MarineTraffic was a key reference throughout that project, and at some point I went from using the website to poking at the API.\nThat is when I found something I was not supposed to find.\nMarineTraffic sells API access at different subscription tiers, with paid plans unlocking richer tracking data. I was on a free account and making requests to compare what different endpoints returned. One of them was returning data that, according to their documentation, should have been restricted to paid subscribers.\nI reproduced it a few times to make sure I was not misreading the response. I was not. The paywall existed on the surface but the API itself had no subscription validation. Anyone with a free account and a bit of curiosity could access paid data just by knowing which endpoint to call.\nI reported it. Not through a generic contact form but by finding the right person to talk to. I ended up in a conversation with their Head of Engineering, which felt surreal for a student who had only recently figured out how any of this worked.\nThey fixed it. And then they offered me an internship.\nI did not take it. I had other plans. But I kept the story.\nMarineTraffic has since been acquired by Kpler.\n","permalink":"https://victorperez.tech/security/marinetraffic/","summary":"I found an endpoint that returned paid-tier ship tracking data without checking subscription level. A CS student, a curious HTTP request, and a conversation with their Head of Engineering.","title":"How I Got Free Access to MarineTraffic's Paid API as a Student"},{"content":" ❮ ❯ The truth is, I don\u0026rsquo;t have a Netflix account, so I never actually watched The Squid Game. But spending even a minute with friends or scrolling through social media made it clear that it had become a global phenomenon. Around that time, I was looking for an excuse to start building with Unity, and a viral show about games felt like the perfect source of free ideas.\nMy experience with Unity was surprisingly good. It felt more production-ready than GameMaker1 (amazing piece of software, by the way!), most of the basics are handled automatically by the IDE, which lets you focus on the fun technical parts. I learned how to load textures and sprites, and how to implement basic logic in C#.\nThe game itself was simple: you held your finger down to make the character run while the gun wasn’t pointing at you, and had to release it before it turned back. No warning, and each round got faster. Really frustrating, which probably meant it worked as intended.\nIt was a fun first contact, and gave me the feeling that I could learn quickly and eventually get good at making (simple) games. Still, I realized I was more interested in regular apps, so I didn’t take it further.\nI used GameMaker around 2012, back when the IDE was still called GameMaker Studio. I\u0026rsquo;m not sure about its current adoption or evolution, but a quick search in 2025 shows that it\u0026rsquo;s come a long way.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"https://victorperez.tech/projects/ragequit/","summary":"My first Unity game, inspired in The Squid Game\u0026rsquo;s \u0026ldquo;Red Light, Green Light\u0026rdquo;.","title":"The Rage Quit Game"},{"content":"\nA few months after winning the HSD hackathon, the project had grown into something more than just an MVP. Once again, an ad on LinkedIn crossed my path: Huawei AppsUP.\nIt turned out they weren\u0026rsquo;t only organizing hackathons for students - the cool kids had their own league. I remember spotting Civitatis, the largest tour guide directory in Spain, among the participants and immediately thinking, \u0026ldquo;challenge accepted.\u0026rdquo;\nI spent the whole summer polishing the design, adding missing features like pharmacy finding, and squashing as many bugs as I could. And once again, minutes before the deadline, I submitted my application.\nThe outcome was so positive it even got people writing about it! If you’re curious about what they said, google \u0026ldquo;Víctor Pérez Clover\u0026rdquo; and you\u0026rsquo;ll find a bunch of results. What\u0026rsquo;s more, it even got me talking about myself at the company\u0026rsquo;s main event in Paris! Nevertheless, Clover wasn’t just a three-day grace, and I was ready to take it to the next level: make it compatible with smartwatches.\n","permalink":"https://victorperez.tech/awards/clover-appsup21/","summary":"For Clover","title":"Huawei AppsUP 2021: Excellent Student Award"},{"content":" ❮ ❯ By the time I started this app, I felt that I already had sufficient knowledge of how Android worked and decided to venture into some of Google’s APIs, building on my experience fighting1 with Huawei’s.\nI began with ML Kit, a library that has come a long way since 2021, when I wrote this app. At that time, I chose to keep it simple and use its OCR technology to sum the numbers it detected.\nArs Technica was so painfully accurate that I still remember this quote today: \u0026ldquo;Huawei\u0026rsquo;s dev documents are psychological warfare.\u0026rdquo;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"https://victorperez.tech/projects/banknotes/","summary":"Quick CameraX and ML Kit project. Use your camera to count your money.","title":"AI Banknote Scanner"},{"content":" ❮ ❯ This was my first and only experience with keyboard customization. The amount of boilerplate code involved quickly convinced me not to try it again. Still, it turned out to be a useful experiment, since it gave me the chance to test AdMob’s Rewarded Ads.\n","permalink":"https://victorperez.tech/projects/hypebeast/","summary":"Rizz up your keyboard.","title":"Hypebeast Keyboard"},{"content":" ❮ ❯ Back in 2012, I spent way too much time playing with instant button apps, so when I finally got the chance to make my own, I went all in and built four.\nAs viral videos and streamers kept shaping the Spanish entertainment scene, I started creating small projects to learn more about the MediaPlayer library and to experiment with in-app purchases.\nTwo of those apps even went viral, hitting the #1 spot in the Personalization chart on Google Play Spain and reaching over 8,500 users.\n","permalink":"https://victorperez.tech/projects/soundboards/","summary":"Soundboard apps with quotes from Spanish streamers. Reached the top Google Play charts and 1000+ concurrent users.","title":"Soundboard Apps"},{"content":"\nWhere everything started. 6 months after my first contact with apps, I decided to join this hackathon. I was pursuing my degree at that time, and thought it\u0026rsquo;d be beneficial to increase my exposure to the corporate world in ways the university couldn\u0026rsquo;t already help me with. A few days later, I stumbled upon an ad on LinkedIn. The rest is history.\nBack in 2020, Huawei was starting to market their Huawei Mobile Services APIs among students as part of an expansion strategy in Europe. Parallely, they launched the Huawei Student Developers and Huawei Developer Groups to compete against Google\u0026rsquo;s. Turns out, I was caught in the eye of the storm.\nThere were 180 Spanish students in that hackathon, which took place online. The only requirement was to implement one or more HMS capabilities, and then a jury would decide on three winners.\nI recently had visited my grandmother a few weeks before the competition, and I realised her way of keeping track of her medications was as unique as it was dangerous: marking shapes and colors on her calendar. We had gifted her a smartphone some months before the visit, so the dots connected almost instantly: I was going to create the first pill reminder for specially designed for senior citizens.\nSince I was in the middle of my exams season, I only had 2 weeks to prototype an app, instead of the 3 they gave us. After a wild ride designing, dealing with Huawei\u0026rsquo;s documentation (a true maze), and breaking the whole app an hour before the deadline, I managed to submit it on time.\nWith this win, I gained the confidence to continue the development of Clover and turning it into what was going to become my biggest, most successful project to date.\n","permalink":"https://victorperez.tech/awards/clover-hsd/","summary":"For Clover","title":"Winner of the Huawei Student Developers Hackathon"},{"content":"Acciona (BMAD: ANA.MC), is a Spanish multinational conglomerate dedicated to the development and management of infrastructure (construction, water, industrial and services) and renewable energy. The company is listed in the IBEX 35 index and is a national industry benchmark.\nI joined as an intern as part of the company\u0026rsquo;s scholarship program, which was granted to a selection of Spanish students. I worked for the Mobility division, which operates the world\u0026rsquo;s largest shared motorbike network, according to the company in 2020.\nI mainly helped the Marketing team at querying, cleaning and presenting data so they could make informed decisions. This often involved leveraging Python\u0026rsquo;s SQLAlchemy and Pandas, and then using an external tool such as Excel or Power BI to visualize the data.\nAs part of my university program, I also completed my end-of-degree dissertation, which analyzed potential zones of constrained demand for motorbikes in the city of Barcelona, earning a grade of 9 out of 10.\n","permalink":"https://victorperez.tech/experience/acciona/","summary":"Data Science Intern. Scholarship awarded. EV bike rental division.","title":"Acciona"},{"content":" ❮ ❯ My third app was developed, once again while COVID restrictions were still in place. Around that time, bars started replacing paper menus with QR codes. Even though most phones could scan QR codes directly from the camera app, many people either didn’t know that or preferred to save their scans for later.\nThat’s exactly what I built the app for. It was a great opportunity to start experimenting with actual hardware, capturing an image and processing it. My dad still uses it today.\n","permalink":"https://victorperez.tech/projects/scanner/","summary":"Simplest QR scanner ever. And my first CameraX app.","title":"QR Scanner"},{"content":" ❮ ❯ Starting out as a developer during lockdown gave me plenty of time to brainstorm app ideas, though actually building them was often tricky because of the constantly changing legal restrictions. One day, after hearing about social distancing rule changes yet again, I decided to turn that into my next project.\nFloorPlanner was an app that helped users arrange items such as restaurant tables or beach hammocks in a way that was both efficient and compliant. Users could enter the size of a room and its items, add optional thresholds (for example, to include chairs around tables), and define the required social distance. The app would then generate a coordinate map showing the most efficient and compliant layout.\nThis project was a lot of fun to build. After my first experience with the Canvas library in my Political Compass project, FloorPlanner allowed me to learn how to draw more complex elements and better understand the\u0026hellip; quirks of RecyclerView.\n","permalink":"https://victorperez.tech/projects/floorplanner/","summary":"My second app. Arrange things to comply with COVID-19 distancing guidelines.","title":"FloorPlanner"},{"content":" ❮ ❯ After three failed attempts, this was the beginning of everything. Summer of 2020, during severe lockdown, no more university classes. I had recently stopped developing YPSILON after two years of near full-time dedication, and I finally felt confident enough in Java to give Android another try.\nI wanted to start simple. I grabbed Google\u0026rsquo;s documentation, got a few pages in, and then switched to YouTube tutorials. Soon enough, I wanted to fly solo: tutorials were informative but not particularly rewarding. Instagram was big on memes about the political compass around that time, and I thought a simple question game would be easy enough to write. As with anything you do for the first time, it wasn\u0026rsquo;t.\nBut hey, it was honest work and I learned a lot. The app even had moderate moments of glory after I experimented with A/B testing Play Store listings during election periods, which taught me a lot about the foundations of ASO and marketing. Oh, and it was also my first app to reach the Top 3 for free games in the Spanish Play Store!\n","permalink":"https://victorperez.tech/projects/politicalcompass/","summary":"Everything started here. My very first completed project.","title":"The Political Compass"},{"content":"\nThis is a crazy story, buckle up. I really enjoy walking across the Barcelona Port Vell marina: open space, palm trees, the water just a few meters away… a perfect place to unwind, reflect, and maybe sip a good cocktail.\nIt was late 2018, and I was walking there with one of my best friends. I had never really paid attention to the yachts berthed along the marina until I saw a massive one. So massive it covered the buildings behind it1. Its name was Dilbar, and it was the largest private yacht by gross tonnage at that time.\nA few subsequent walks only deepened my curiosity. One night, I opened Wikipedia and started reading about the yacht charter business. In the Spanish article, there used to be a sentence that went something like this:\n“Latest trends in the yacht charter industry involve implementing chatbots, machine learning, and artificial intelligence to customize the customer experience.”\nI looked into applied machine learning in the sector, found nothing, and closed my laptop for the day. An idea was born: I would build an application to help charter agencies recommend the most suitable vessel for a customer based on their previous charter history.\nThe sensation of building something no one else had built felt amazing, but it came with a great responsibility: you have the power to set a standard, but at the same time, more capable people might be secretly working on the same thing. I had to move fast (I didn’t).\nAnyway, I scraped the entire Yacht Harbour yacht database into a SQLite file (if you’re reading this, I’m sorry!) and plugged it into Python, only to decide Java was more suitable for my requirements a few days later.\nFast forward nearly two years, I had a piece of software that would fetch previous vessels from a database using JDBC, and then classify them in two ways:\nFor quantitative attributes, such as length, width, number of rooms, and crew, it would look for similar vessels within n standard deviations, increasing n by one if no matches were found. For qualitative attributes, which were less relevant but still important (shipyard, interior and exterior designer), it would build a layered graph, traverse it recursively, and create tuples. The result was a set of numerical attributes with qualitative tuples that were then used to query the database, producing a customized set of new vessels. In the end, the result was presented as a PDF created with HTML, including similarity percentages for each attribute.\nThe thing is, I did all of this for fun on my legendary ThinkPad T400, running an old version of Eclipse and with no previous knowledge of Java. While I was building it, I thought maybe it was worth showing around, so I cold-emailed several yacht charter agencies and even had calls with some of them.\nIn the end, I was offered an internship at Camper \u0026amp; Nicholsons, which I turned down for a better offer. The call was with their CTO at the time, Giovanni Alessi Anghini, son of Alessio Alessi, of the Alessi design family. Yes, the coffee machines. The software was no big deal in hindsight, but it has a special place in my heart because it set the foundations for everything else you’ll see on this website.\nI found a picture from 2017 taken from the exact same spot where I saw it for the first time. Seems like someone else was impressed enough to post it on Wikipedia.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"https://victorperez.tech/projects/ypsilon/","summary":"My first serious piece of software: a yacht recommendation system.","title":"YPSILON"},{"content":"","permalink":"https://victorperez.tech/advocacy/gsoc/","summary":"Google scholarships granted to students who’d like to spend the summer contributing to open-source projects. I’ve been a mentor for the Liquid Galaxy project in 2022, 2023, and 2025.","title":"Google Summer of Code"},{"content":"","permalink":"https://victorperez.tech/advocacy/hdg/","summary":"Huawei\u0026rsquo;s alternative to Google Developer Groups. I was approached by the company to become an organizer after I graduated. No longer involved.","title":"Huawei Developer Groups"},{"content":"","permalink":"https://victorperez.tech/advocacy/hsdev/","summary":"Huawei\u0026rsquo;s alternative to Google Developer Student Clubs. I was designated as an ambassador while I was a student. No longer involved.","title":"Huawei Student Developers"}]