<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ reverse engineering - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ reverse engineering - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 28 May 2026 16:47:13 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/reverse-engineering/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Reverse Engineer a Website – a Guide for Developers ]]>
                </title>
                <description>
                    <![CDATA[ While using one of your favorite websites, you might have often thought, "What if this website had this particular functionality? That would be great!" If you have ever had such thoughts, this article is for you. In it, you'll learn how websites comm... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-reverse-engineer-a-website/</link>
                <guid isPermaLink="false">6734cea5ae439f84c4b2399b</guid>
                
                    <category>
                        <![CDATA[ reverse engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Programming Blogs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Abdurrahman Rajab ]]>
                </dc:creator>
                <pubDate>Wed, 13 Nov 2024 16:07:01 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/FlPc9_VocJ4/upload/bfbb3d6320985e7e7db8d18465d20af4.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>While using one of your favorite websites, you might have often thought, "What if this website had this particular functionality? That would be great!"</p>
<p>If you have ever had such thoughts, this article is for you. In it, you'll learn how websites communicate with servers and get data and how to work backwards to understand how that website functions.</p>
<p>You will also see how to add functionality to a website or use its APIs to recreate it yourself. You will use a simple demo website in the article to do that. The website contains some sales data grabbed by a remote API. In the demo, you will use the website to see what APIs have been used to get the data and how to use the sales data API.</p>
<p>If you understand how to access the data API on this website, you can use the same methodology to access this data on any website you like.</p>
<h2 id="heading-prerequisites">Prerequisites:</h2>
<p>This article should be accessible to anyone who knows the basics of programming. You will see examples in JavaScript, but you can use these techniques in your favorite language. Having some basic knowledge of how the web works will also be helpful.</p>
<p>You need to install the project from <a target="_blank" href="https://github.com/a0m0rajab/reverse-engineering-lab">GitHub</a> and run it to experiment with this tutorial.</p>
<h2 id="heading-what-well-cover">What We’ll Cover:</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites:</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-an-api">What is an API?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-do-apis-work">How Do APIs Work?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-reverse-engineering">What is Reverse Engineering?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-reverse-engineer-a-website">How to Reverse Engineer a Website</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-explore-the-website">Explore the Website</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-check-the-sales">Check the Sales</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-the-api-on-your-website">How to Use the API on Your Website</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-get-the-authorization-and-explore-it-through-the-website">How to Get the Authorization and Explore it Through the Website</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-next-steps-authorization-and-authentication">Next Steps: Authorization and Authentication</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-wrapping-up">Wrapping Up</a></p>
</li>
</ol>
<h2 id="heading-what-is-an-api">What is an API?</h2>
<p>Application programming interfaces (APIs) allow two computer programs to communicate. You request the data you want to use in your project from an API, and the API fetches it for you.</p>
<p>These APIs can be local (like Windows APIs, Web APIs, and so on) or remote (like the APIs that developers provide through the internet, such as the Weather API and website APIs).</p>
<p>This article will focus on remote APIs, since developers often use this approach on modern websites. Websites use APIs to display results based on a response.</p>
<p>Some companies might provide access to their APIs so you can develop on top of them, but this is only the case for some. Sometimes, an API might need to provide the functionality or design you want. So, first, you should look at what a site offers and use it to create the features you want.</p>
<p>In this tutorial, you will learn how to understand and explore the APIs behind a website so you can use them in your projects. You will first learn how APIs work, then explore what reverse engineering means. Then, you'll use a demo website and an example through Postman, where you will use an API to get some data from the website. You'll be able to use this data anywhere you want.</p>
<h2 id="heading-how-do-apis-work">How Do APIs Work?</h2>
<p>The structure of an API contains two levels: the client and the server. The client requests data from the API, and the server provides it. This technology has been around for a long time and is now standardized.</p>
<p>The client starts to request the data by connecting with the correct endpoint and providing the related information for the server. The server checks this data, and based on that, it does its magic and returns a response to the client about which process to use.</p>
<p>Here is a simple drawing showing this process:</p>
<p><img src="https://voyager.postman.com/illustration/diagram-what-is-an-api-postman-illustration.svg" alt="An explanation of APIs by the Postman team (From: What is an API? A Beginner's Guide to APIs | Postman)" width="600" height="400" loading="lazy"></p>
<p>API requests and responses usually have a similar structure, which is:</p>
<p>Request:</p>
<ul>
<li><p>Endpoints: the target URL of the API.</p>
</li>
<li><p>Methods: tell the server what to do with data, like get the data, update it, delete it, and so on.</p>
</li>
<li><p>Parameters: extra details you provide to the server for additional requests, like the topic, category, and so on.</p>
</li>
<li><p>Headers: these key-value pairs provide information about the client, authentication, and more.</p>
</li>
<li><p>Body: this is the actual data provider, which includes whatever the client wants from the server.</p>
</li>
</ul>
<p>Response:</p>
<ul>
<li><p>Status code: this three-digit HTTP status code tells the client about the server's result.</p>
</li>
<li><p>Header: this is similar to the request but has the server's information. It could be setting cookies or other details.</p>
</li>
<li><p>Body: has the actual data from the server to use.</p>
</li>
</ul>
<p>Now that you know a bit about APIs and HTTP requests, you can reverse engineer a website.</p>
<h2 id="heading-what-is-reverse-engineering">What is Reverse Engineering?</h2>
<p>Reverse engineering is the art of analyzing a system to understand how developers built it. It helps you figure out how it functions so you can improve or hack it.</p>
<p>Some people use reverse engineering to crack programs. Others use it to customize them or even add extra functionalities.</p>
<p>As for websites, the reverse engineering process will help you understand what APIs a site has and how it's using them. It enables you to write your program based on the site's APIs.</p>
<p>Sometimes, reverse engineering can be used to find bugs, crack software, or even use an API without permission. Website developers tend to prevent that by providing an official API for their website, setting limits for API usage, and detecting any unauthorized use.</p>
<p>For this reason, when you start to reverse engineer any program, you will need to consider the terms of use and the legal side of your work so that you’re not doing anything illegal or unethical.</p>
<h2 id="heading-how-to-reverse-engineer-a-website">How to Reverse Engineer a Website</h2>
<p>To reverse engineer a website, you need to do two things: first, you need to explore the website to see how it works and learn what kind of data and endpoints it provides. Second, you need to set some assumptions about how it works and try to validate the assumptions.</p>
<p>A simple assumption would be that after logging into the website, the website receives authentication information through API requests. Getting this information will allow you to use the website APIs without the need to log in every time.</p>
<p>To validate this assumption, you'll need to investigate the requests sent and received by the website. Then you'll need to send your requests by yourself from an external source like your terminal through CURL or HTTP client like Postman.</p>
<p>I have created a demo website that we'll reverse engineer. You'll run the website on your computer and then reverse-engineer it. The website shows you a simple login page and has some customer data. Your goal will be to get the customer's recent sales data.</p>
<p>Here are a couple screenshots of the website and what you have:</p>
<p>Page 1: Login:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731438727536/cfb07e6b-2416-41c7-a24e-1cf52b1943b0.png" alt="Screenshot of the login page" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Page 2: The website data</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731258198260/8c96ed82-a288-4141-b97d-e97e71e6412e.png" alt="Screenshot of the data page" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-explore-the-website">Explore the Website</h3>
<p>The first step in reverse engineering is to explore the website and see how it works. To do this, you'll use Chrome developer tools to check the requests sent by the website and see how they affect it. You'll also look for data received by those requests and see how you can use them.</p>
<p>At the same time you'll need to filter the requests since some of them don't send or receive data, but they get various files that the website uses, like CSS files or images.</p>
<p>Chrome developer tools help you analyze and understand a website, showing you the HTML elements, network, and storage that the website uses.</p>
<h3 id="heading-check-the-sales">Check the Sales</h3>
<p>Your target is to check the website's sales, so you need to log in to access the website and go to the dashboard page to check the sales.</p>
<p>On the sales page, you will do the following:</p>
<p>First, open Chrome dev tools (by either clicking on F12 or right-clicking anywhere, then opening Inspector) to see what kind of APIs the website provides.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731258258531/1e50c70c-1b97-49a4-aed5-a821c56d638d.png" alt="Chrome right-click menu" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Then, after opening the dev tools, you need to go to the network tab to check the network requests and see what the website sends to the server.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731258501092/3c0e3879-981b-48e2-95a9-736212152938.png" alt="Network tab in the Chrome developer tools" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>The network tab shows you the requests sent from the website to the server and how the server has responded to them.</p>
<p>As you can see in the previous image, you have an empty network in the dev tools. An empty network happens when you open the dev tools after the website sends the calls. A refresh (F5) on the website will be enough to check the calls.</p>
<p>In the following image, you can see the requests sent from the website to the server. If you analyze the request names, you will find one of the requests called <code>sales</code>, which is the one that has sales data. You can open the call and see the result of it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731258473336/5b627ea4-9b84-440d-a6e4-d3b5a99714a6.png" alt="Showing sales endpoints from the network tab in Chrome developer tools" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>If you click on the call, you will see that you have the headers, cookies, responses, and so on.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731258693963/69337d7d-79e1-4f16-b161-dc9401cb3c73.png" alt="Showing the headers of the API endpoint from Chrome dev tools" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>These tabs will help you understand the result of the call, the origin, and the request and response of the request. If you go to the response tab, you can see the sales data as JSON, which is what the website uses.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731258724075/6b1610e9-9919-4de1-beac-c57aa32d5768.png" alt="Showing the response of the API endpoint from network developer tools" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Right now, since you have this call, you can use it in the browser to get the result. To do this, you need to use the fetch function from JavaScript. This approach will help you see the function's result and how it works.</p>
<p>A simple way to do that is to click on the call, then go to “copy,” and choose “copy as fetch”. In this case, “fetch it” means copying the request to reuse as a fetch call in JavaScript, with all of the headers and body included in the copied text.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731258767702/46715fa0-1abc-4d57-8912-3a84032b4d31.png" alt="The steps to copy the API endpoint as fetch" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Here is the code of the fetch:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> fetchResult = fetch(<span class="hljs-string">"http://localhost:3000/api/sales"</span>, {
<span class="hljs-string">"headers"</span>: {
<span class="hljs-string">"accept"</span>: <span class="hljs-string">"*/*"</span>,
<span class="hljs-string">"accept-language"</span>: <span class="hljs-string">"en,tr-TR;q=0.9,tr;q=0.8,en-US;q=0.7,ar;q=0.6,it;q=0.5"</span>,
<span class="hljs-string">"sec-ch-ua"</span>: <span class="hljs-string">"\"Chromium\";v=\"124\", \"Google Chrome\";v=\"124\", \"Not-A.Brand\";v=\"99\""</span>,
<span class="hljs-string">"sec-ch-ua-mobile"</span>: <span class="hljs-string">"?0"</span>,
<span class="hljs-string">"sec-ch-ua-platform"</span>: <span class="hljs-string">"\"Windows\""</span>,
<span class="hljs-string">"sec-fetch-dest"</span>: <span class="hljs-string">"empty"</span>,
<span class="hljs-string">"sec-fetch-mode"</span>: <span class="hljs-string">"cors"</span>,
<span class="hljs-string">"sec-fetch-site"</span>: <span class="hljs-string">"same-origin"</span>
},
<span class="hljs-string">"referrer"</span>: <span class="hljs-string">"http://localhost:3000/dashboard"</span>,
<span class="hljs-string">"referrerPolicy"</span>: <span class="hljs-string">"strict-origin-when-cross-origin"</span>,
<span class="hljs-string">"body"</span>: <span class="hljs-literal">null</span>,
<span class="hljs-string">"method"</span>: <span class="hljs-string">"GET"</span>,
<span class="hljs-string">"mode"</span>: <span class="hljs-string">"cors"</span>,
<span class="hljs-string">"credentials"</span>: <span class="hljs-string">"include"</span>
})
</code></pre>
<p>You can consume this call by using this code:</p>
<pre><code class="lang-js">fetchResult.then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> res.json()).then(<span class="hljs-built_in">console</span>.log)
</code></pre>
<p>Here is the result of the fetch:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731258819878/45eebd69-3af1-4474-b221-65c527ead3eb.png" alt="The promise results in the console" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>As you can see, you were able use the API to get the sales results and explore them. You can now use this data anywhere on the current website and fetch the sales API programmatically.</p>
<p>Doing this fetch through the browser's developer tools will assume that you are doing it in the website's name. This will add extra headers to the API request, like the current website hostname in the headers and current cookies attached to the API request.</p>
<p>But what if you're going to use the API outside the same website? You might wish to use the API on your website or a server. By using it on your website, I mean getting the sales data and showing it as a widget on your website, or even getting these data to store them on your server and process them to do data mining.</p>
<p>Using the data outside the host website would require a different hostname to be attached to the headers and other cookies connected to the API request. For these cases, you will need to use Postman, an HTTP request-testing software that helps you test, explore, and read API request data.</p>
<h3 id="heading-how-to-use-the-api-on-your-website">How to Use the API on Your Website</h3>
<p>Since you got the API endpoint from the previous section, which was the following:</p>
<pre><code class="lang-bash">http://localhost:3000/api/sales
</code></pre>
<p>You might expect to use this URL and fetch the data you used before – and have it work immediately in Postman and be able to use it on your website. But it doesn’t work like this, since this fetch request does not contain any data about the authorization.</p>
<p>You can try it in Postman yourself to see the error. Postman provides two ways to write the fetch URL: the first one is to write the call in the Postman UI, and the other one is to import the API call to try it (as you can see in the image below).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731260011131/b41277da-4b01-4212-a577-27491948ec94.png" alt="Screenshot from Postman showing where to paste the url" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>To import the fetch request to Postman, first you need to click on the call from the network tab and copy it as:</p>
<ol>
<li><p>cURL (Bash), then paste it to Postman. Copying the call as cURL (Bash) will allow you to get the headers and all related data from the website, like cookies, and so on.</p>
</li>
<li><p>URL only, which will have the URL without having extra data.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731260138355/3411bf8b-23b8-4a16-88fa-bfb4601458c0.png" alt="Screenshot from devtools showing how to copy as curl" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>For this article, you will copy it as a URL and paste it into Postman. You'll do that to get a clean API call without the connected headers and cookies. Then, you'll click on the send button in Postman to make the request and get the result from the API.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731260209476/b8c1633b-299a-4cca-afc5-1dee704be170.png" alt="Postman interface showing where to paste the URL" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>When you click on send, you will see that you've gotten an unauthorized message from the API body and a status code of 200. The unauthorized message happened because you did not log into the website from Postman, and the status code is due to the API design. Some APIs might return a status code 401: unauthorized, which you might encounter on other websites.</p>
<p>Being unauthorized means that you are not logged in and do not have permission to use this specific API. Some APIs are public, which you can use without any API key or extra details. Other APIs need authorization in terms of using a username and password or even a key provided by the API provider.</p>
<p>In this example, we are using a private API which needs to be authorized. Here you are getting the data that you are only allowed to access.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731260251132/aeb7c25c-6c39-475b-8e36-f265f8c7462c.png" alt="Postman screenshot showing the API body and the status" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-get-the-authorization-and-explore-it-through-the-website">How to Get the Authorization and Explore it Through the Website</h3>
<p>Based on the previous section, when you tried the API call, you got a message telling you that you are unauthorized. The request needs authorization.</p>
<p>So you need to establish an assumption about authorization by saying that you can get the authorization information from the login page in the demo website. For the assumption here, you might think about how the website is using the username and password to record the session. Usually websites record the session through cookies.</p>
<p>After getting logged in, you will be able use the API call to get the data you want.</p>
<p>To try that, you can go through the following steps:</p>
<p>To figure out what the website is doing to get authorized, you can either:</p>
<ul>
<li><p>Try copying the URL as bash and seeing what extra cookies and options you get</p>
</li>
<li><p>Try logging in, getting the data from the login, and sending it to the protected call</p>
</li>
</ul>
<h4 id="heading-checking-the-login-method">Checking the login method</h4>
<p>You need to figure out how the website login function works and what data is being sent to the server to verify the API request and get authorized. So, you should check the login page and analyze the requests.</p>
<p>Here are the steps:</p>
<ul>
<li><p>Go to the login page</p>
</li>
<li><p>Open the dev tools</p>
</li>
<li><p>Go to the network tab</p>
</li>
<li><p>Click on the login button</p>
</li>
</ul>
<p>When you click on login, enable the preserve log option to preserve logs when you browse through different pages or the website redirects you.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731263927757/4cfb87f3-4688-403e-af6d-184a2c2f4aa9.png" alt="Showing the network tab from developer tools focusing on preserving log and the login endpoint" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>As you can see from the image above, you got a login call from the website. You need to explore the call and see what results you get from it. Here is the explanation of the data from the response:</p>
<p>The response:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731263967453/56dadf64-14dc-48bc-a81b-b04cafca95e4.png" alt="Showing the response tab from the network Chrome developer tools" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>In the above image, you can see that you got a message that just says “ok”, which does not provide much detail. Right now, you need to check the headers and the cookies to see what the server sent and if you can use the server headers for authentication.</p>
<p>If you check the headers, you can find a response header called set-cookie, which is responsible for setting a cookie on your machine. This one has a <code>loggedin=true</code> value, indicating a log-in flag that the website could use.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731264427158/4f084e2a-b84a-4d5c-95b6-35ebfc725ab6.png" alt="Showing the set-cookie response header from headers" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>You will see the same value when you go to the cookies tab.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731264453607/8ad16508-b19d-4b69-89ba-6e796d7f0120.png" alt="Showing the cookies header, focusing on the logged value" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Here, you might think that having a cookie sent with the “sales” request header could authorize the request. To double-check that, you can open the sales request from the dev tools and see what extra details the request headers have, from headers or cookies:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731264041695/ca811292-ae3a-4bb1-a33c-4a046b19ff4a.png" alt="Showing the headers, then request headers and cookies" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>If you go to the cookies tab, you will notice the request did send the same cookies:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731263995185/bcc7f3ee-e510-42cb-817d-94a8f31472f6.png" alt="Showing the cookies tab with request cookies and focusing on the provided cookie" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>To ensure the cookies are the reason, you can return to the Postman call and add a cookie to test the call.</p>
<p>You need to do the following:</p>
<ul>
<li><p>Open the headers tab</p>
</li>
<li><p>Add cookie as header</p>
</li>
<li><p>Send the request</p>
</li>
<li><p>Check the result</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731264213696/85b535b9-d488-4bff-95f3-8fecb5093f1e.png" alt="Postman screenshot focusing on headers, showing the cookie, status, and the data" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>As you can see, you got a result of the data, which means that the server authorized the request, and you can access the data. Getting the data confirms the hypothesis you set in the beginning: the endpoint needs authentication.</p>
<h4 id="heading-checking-the-sales-with-curl-bash">Checking the sales with cURL (Bash)</h4>
<p>A more straightforward and more accessible way to do this would be by copying the request as cURL (Bash), which brings all the options to Postman. Then, you need to analyze the options and see what headers the server sent for authorization.</p>
<p>You can check out the following image, which has the URL pasted as cURL (Bash):</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731264264606/f45c11c6-7121-4702-a57e-9435252d7245.png" alt="Postman screenshot showing the headers and focusing on the cookie key." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>In the image, you can see that you have added 12 extra headers, and you can check them and analyze them. Sometimes, you might find an authorization header. Other times, you might have other token headers that you need to consider.</p>
<p>When you notice the header responsible for authorization, you need to go back to the website and analyze it from the beginning to check which endpoint provides the related authorization. You did it the hard way at the beginning to enable you to understand how to authenticate if the cookies were a token or something that would be challenging to figure out.</p>
<p>As you will see in the next section, website authentication is getting more complicated daily, and you must be ready to try all of the methods.</p>
<h3 id="heading-next-steps-authorization-and-authentication">Next Steps: Authorization and Authentication</h3>
<p>Authentication and security are significant issues. As you noticed on the website, you had to use the cookies to show authentication, which would be valid for some websites.</p>
<p>Other websites might have more advanced encrypted methods to authenticate and authorize. For those situations, basic knowledge and curiosity will help you explore and use the APIs from the website.</p>
<p>Some websites use the OAuth standards to authorize, saving a token on the website to send requests. As you move forward and reverse engineer more websites, you will notice the different patterns and will be able to understand them and become better at this work.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>This article was for educational purposes, which is why we used a clean website to help you see things quickly.</p>
<p>In real-world examples, things are complicated, and you'll need to explore them more. But the main principles stay similar for all situations: one endpoint brings the authorization/authentication data and another that brings the related data.</p>
<p>Reverse engineering is not easy and requires a fair bit of patience, dedication, and persistence. As you can see, understanding the website takes a lot of time. Not all websites have clean API calls, and some have the calls mixed with a different number of files needed for the website, such as CSS scripts or even images. All you need is to be patient and try to think outside the box.</p>
<p>If you like this article, subscribe to my <a target="_blank" href="https://hadithtechen.substack.com/">newsletter</a> and follow me on <a target="_blank" href="https://www.freecodecamp.org/news/p/f2a5144e-e6e3-479d-a672-caf80e7431d2/twitter.com/a0m0rajab">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How I solved a simple CrackMe challenge with the NSA’s Ghidra ]]>
                </title>
                <description>
                    <![CDATA[ By Denis Nuțiu Hello! I’ve been playing recently a bit with Ghidra, which is a reverse engineering tool that was recently open sourced by the NSA. The official website describes the tool as: A software reverse engineering (SRE) suite of tools develo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-i-solved-a-simple-crackme-challenge-with-the-nsas-ghidra-d7e793c5acd2/</link>
                <guid isPermaLink="false">66c34e17465d1b2f886ba3f7</guid>
                
                    <category>
                        <![CDATA[ hacking ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ reverse engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 20 Mar 2019 15:30:50 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*9N3SURf2cF4fISICAH7tGA.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Denis Nuțiu</p>
<p>Hello!</p>
<p>I’ve been playing recently a bit with <a target="_blank" href="https://ghidra-sre.org/">Ghidra</a>, which is a reverse engineering tool that was recently open sourced by the NSA. The official website describes the tool as:</p>
<blockquote>
<p><em>A software reverse engineering (SRE) suite of tools developed by NSA’s Research Directorate in support of the Cybersecurity mission.</em></p>
</blockquote>
<p>I’m at the beginning of my reverse engineering career, so I didn’t do anything advanced. I don’t know what features to expect from a professional tool like this, if you’re looking to read about advanced Ghidra features this is likely not the article for you.</p>
<p>In this article I will try to solve a simple CrackMe challenge that I’ve found on the website <a target="_blank" href="https://www.root-me.org/">root-me</a>. The challenge I’m solving is called <a target="_blank" href="https://www.root-me.org/en/Challenges/Cracking/ELF-CrackPass">ELF - CrackPass</a>. If you want to give it try by yourself, then you should consider not reading this article because it will spoil the challenge from you.</p>
<p>Let’s get started! I open up Ghidra and create a new Project which I call RootMe.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/t6VRANxq75gcBUE7GDwEho2IqpOJ6DC4NGt0" alt="Image" width="800" height="559" loading="lazy"></p>
<p>Then I import the challenge file by dragging it to the project folder. I will go with the defaults.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/y2KMPmw-nfQlH9gn9ZJxP2Zqk5XZgrTD1lGF" alt="Image" width="800" height="470" loading="lazy"></p>
<p>After being presented with some info about the binary file, I press OK, select the file, and double click it. This opens up Ghidra’s code browser utility and asks if I want to analyse the file, then I press Yes and go on with the defaults.</p>
<p>After we import the file, we get some information about the binary file. If we press OK and dismiss this window, and then double click the file we imported, this opens up Ghidra’s code browser utility. I select Yes when prompted to analyze the binary and go on with the defaults.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/zBOQtrTVrg3SebAl14mSBlRknf4qJrM2VBKY" alt="Image" width="800" height="867" loading="lazy"></p>
<p>The Code Browser is quite convenient. In the left panel we get to see the disassembly view and in the right panel the decompile view.</p>
<p>Ghidra shows us directly the ELF header info and the entry point of the binary. After double clicking the entry point, the dissembler view jumps to the entry function.</p>
<p>Now we can successfully identify the main function, which I rename to main. It would be nice if the tool would attempt to automatically detect the main function and rename it accordingly.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/7Ng0waaxWM2LhOlomKpuNfPmJudV8uido7WJ" alt="Image" width="800" height="501" loading="lazy"></p>
<p>Before analyzing the main function, I wanted to change its signature. I changed the return type to int and corrected the parameters’ type and name. This change has taken effect in the decompile view which is cool! ?</p>
<p>Highlighting a line in the decompile view also highlights it in the assembly view.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/2HOWsHwRO1EjjGH7Kwv4Dmvu-KVrMSkNL0yj" alt="Image" width="800" height="502" loading="lazy"></p>
<p>Let’s explore the FUN_080485a5 function, which I’ll rename to CheckPassword.</p>
<p>The contents of the CheckPassword function can be found below. I’ve copied the code directly from Ghidra’s decompile view, which is a neat feature that many tools of this type lack! Being able to copy assembly and code is a nice to have feature.</p>
<pre><code><span class="hljs-keyword">void</span> CheckPassword(char *param_1) {   ushort **ppuVar1;   int iVar2;   char *pcVar3;   char cVar4;   char local_108c [<span class="hljs-number">128</span>];   char local_100c [<span class="hljs-number">4096</span>];   cVar4 = param_1;       <span class="hljs-keyword">if</span> (cVar4 != <span class="hljs-number">0</span>) {          ppuVar1 = __ctype_b_loc();           pcVar3 = param_1;           <span class="hljs-keyword">do</span> {               <span class="hljs-keyword">if</span> (((byte )(ppuVar1 + (int)cVar4) &amp; <span class="hljs-number">8</span>) == <span class="hljs-number">0</span>) {         puts(<span class="hljs-string">"Bad password !"</span>);                     <span class="hljs-comment">/* WARNING: Subroutine does not return */</span>         abort();       }       cVar4 = pcVar3[<span class="hljs-number">1</span>];       pcVar3 = pcVar3 + <span class="hljs-number">1</span>;     } <span class="hljs-keyword">while</span> (cVar4 != <span class="hljs-number">0</span>);   }   FUN_080484f4(local_100c,param_1);   FUN_0804851c(s_THEPASSWORDISEASYTOCRACK_08049960,local_108c);   iVar2 = strcmp(local_108c,local_100c);   <span class="hljs-keyword">if</span> (iVar2 == <span class="hljs-number">0</span>) {     printf(<span class="hljs-string">"Good work, the password is : \n\n%s\n"</span>,local_108c);   }   <span class="hljs-keyword">else</span> {     puts(<span class="hljs-string">"Is not the good password !"</span>);   }   <span class="hljs-keyword">return</span>; }
</code></pre><p>After taking a look at the code, I’ve come to the following conclusions. The block with the <code>if</code> checks if the user has provided a password and inspects the provided password to check if it’s a valid character or something. I’m not exactly sure what it’s checking for, but here’s what __ctype_b_loc()’s documentation says:</p>
<blockquote>
<p>_The __ctype_b<em>loc() function shall return a pointer into an array of characters in the current locale that contains characteristics for each character in the current character set. The array shall contain a total of 384 characters, and can be indexed with any signed or unsigned char (i.e. with an index value between 128 and 255). If the application is multi-threaded, the array shall be local to the current thread.</em></p>
</blockquote>
<p>Anyways, that block of code is not really worth the time, because it doesn’t modify our password in any way, it just verifies it. So we can skip this kind of verification.</p>
<p>The next function called is FUN_080484f4. Looking at its code, we can tell that it’s just a custom memcopy implementation. Instead of copying the C code from the decompiler view, I copied the assembly code — yes, this is fun.</p>
<pre><code>*************************************************************                     *                           FUNCTION                                               *************************************************************                     <span class="hljs-literal">undefined</span>  FUN_080484f4 (undefined4  param_1 , undefined4  p     <span class="hljs-literal">undefined</span>         AL:<span class="hljs-number">1</span>           &lt;RETURN&gt;     undefined4        Stack[<span class="hljs-number">0x4</span>]:<span class="hljs-number">4</span>   param_1                                 XREF[<span class="hljs-number">1</span>]:     <span class="hljs-number">080484</span>f8 (R)        undefined4        Stack[<span class="hljs-number">0x8</span>]:<span class="hljs-number">4</span>   param_2                                 XREF[<span class="hljs-number">1</span>]:     <span class="hljs-number">080484</span>fb (R)                        FUN_080484f4                                    XREF[<span class="hljs-number">1</span>]:     CheckPassword:<span class="hljs-number">080485</span>f5 (c)    <span class="hljs-number">080484</span>f4 <span class="hljs-number">55</span>              PUSH       EBP <span class="hljs-number">080484</span>f5 <span class="hljs-number">89</span>  e5           MOV        EBP ,ESP <span class="hljs-number">080484</span>f7 <span class="hljs-number">53</span>              PUSH       EBX <span class="hljs-number">080484</span>f8 <span class="hljs-number">8</span>b  <span class="hljs-number">5</span>d  <span class="hljs-number">08</span>       MOV        EBX ,dword ptr [EBP  + param_1 ] <span class="hljs-number">080484</span>fb <span class="hljs-number">8</span>b  <span class="hljs-number">4</span>d  <span class="hljs-number">0</span>c       MOV        ECX ,dword ptr [EBP  + param_2 ] <span class="hljs-number">080484</span>fe <span class="hljs-number">0</span>f  b6  <span class="hljs-number">11</span>       MOVZX      EDX ,byte ptr [ECX ] <span class="hljs-number">08048501</span> <span class="hljs-number">84</span>  d2           TEST       DL,DL <span class="hljs-number">08048503</span> <span class="hljs-number">74</span>  <span class="hljs-number">14</span>           JZ         LAB_08048519 <span class="hljs-number">08048505</span> b8  <span class="hljs-number">00</span>  <span class="hljs-number">00</span>       MOV        EAX ,<span class="hljs-number">0x0</span>             <span class="hljs-number">00</span>  <span class="hljs-number">00</span>                         LAB_0804850a                                    XREF[<span class="hljs-number">1</span>]:     <span class="hljs-number">08048517</span> (j)    <span class="hljs-number">0804850</span>a <span class="hljs-number">88</span>  <span class="hljs-number">14</span>  <span class="hljs-number">03</span>       MOV        byte ptr [EBX  + EAX *<span class="hljs-number">0x1</span> ],DL <span class="hljs-number">0804850</span>d <span class="hljs-number">0</span>f  b6  <span class="hljs-number">54</span>       MOVZX      EDX ,byte ptr [ECX  + EAX *<span class="hljs-number">0x1</span>  + <span class="hljs-number">0x1</span> ]             <span class="hljs-number">01</span>  <span class="hljs-number">01</span> <span class="hljs-number">08048512</span> <span class="hljs-number">83</span>  c0  <span class="hljs-number">01</span>       ADD        EAX ,<span class="hljs-number">0x1</span> <span class="hljs-number">08048515</span> <span class="hljs-number">84</span>  d2           TEST       DL,DL <span class="hljs-number">08048517</span> <span class="hljs-number">75</span>  f1           JNZ        LAB_0804850a                         LAB_08048519                                    XREF[<span class="hljs-number">1</span>]:     <span class="hljs-number">08048503</span> (j)    <span class="hljs-number">08048519</span> <span class="hljs-number">5</span>b              POP        EBX <span class="hljs-number">0804851</span>a <span class="hljs-number">5</span>d              POP        EBP <span class="hljs-number">0804851</span>b c3              RETComment: param_1 is dest, param_2 is src. <span class="hljs-number">08048501</span> checks <span class="hljs-keyword">if</span> src is <span class="hljs-literal">null</span> and <span class="hljs-keyword">if</span> it is it returns <span class="hljs-keyword">else</span> it initializes EAX (index, current_character) <span class="hljs-keyword">with</span> <span class="hljs-number">0.</span> The next instructions move bytes into EBX (dest) <span class="hljs-keyword">from</span> EDX (src).The loop stops when EDX is <span class="hljs-literal">null</span>.
</code></pre><p>And the other function FUN_0804851c generates the password from the “THEPASSWORDISEASYTOCRACK” string. Looking at the decompiled view. we can roughly see how this function works. If we didn’t have that, we would need to manually analyze every assembly instruction from the function to understand what it does.</p>
<p>Then, we compare the previously generated password with the password that we got from the user (the first argument, argv[1]). If it matches, the program says good job and prints it, else it prints an error message.</p>
<p>From this basic analysis, we can conclude that if we patch the program in various places, we can get it to spit the password without us needing to reverse any C function and write code. Patching the program means changing some of its instructions.</p>
<p>Let’s see what we have to patch:</p>
<p>At address 0x0804868c we patch the JNS instruction into a JMP. And voilà, the change is reflected in the decompiler view. The ptrace result check is bypassed.</p>
<pre><code>{   ptrace(PTRACE_TRACEME,<span class="hljs-number">0</span>,<span class="hljs-number">1</span>,<span class="hljs-number">0</span>);   <span class="hljs-keyword">if</span> (argc != <span class="hljs-number">2</span>) {     puts(<span class="hljs-string">"You must give a password for use this program !"</span>);                     <span class="hljs-comment">/* WARNING: Subroutine does not return */</span>     abort();   }   CheckPassword(argv[<span class="hljs-number">1</span>]);   <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;}
</code></pre><p>At address 0x080485b8 we patch the JZ instruction into a JMP. We bypass that password verification block we saw earlier.</p>
<pre><code><span class="hljs-keyword">void</span> CheckPassword(undefined4 param_1) {   int iVar1;   char local_108c [<span class="hljs-number">128</span>];   char local_100c [<span class="hljs-number">4096</span>];   CustomCopy(local_100c,param_1);      GeneratePassword(s_THEPASSWORDISEASYTOCRACK_08049960,local_108c);   iVar1 = strcmp(local_108c,local_100c);   <span class="hljs-keyword">if</span> (iVar1 == <span class="hljs-number">0</span>) {     printf(<span class="hljs-string">"Good work, the password is : \n\n%s\n"</span>,local_108c);   }   <span class="hljs-keyword">else</span> {     puts(<span class="hljs-string">"Is not the good password !"</span>);   }   <span class="hljs-keyword">return</span>; }
</code></pre><p>At address 0x0804861e we patch JNZ to JZ. This inverts the if/else condition. Since we don’t know the password, we’re going to submit a random password that is not equal to the generated one, thus executing the printf on the else block.</p>
<pre><code><span class="hljs-keyword">void</span> CheckPassword(undefined4 param_1) {   int iVar1;   char local_108c [<span class="hljs-number">128</span>];   char local_100c [<span class="hljs-number">4096</span>];   CustomCopy(local_100c,param_1);   <span class="hljs-comment">// constructs the password from the strings and stores it in   // local_108c    GeneratePassword(s_THEPASSWORDISEASYTOCRACK_08049960,local_108c);   iVar1 = strcmp(local_108c,local_100c);   if (iVar1 == 0) { // passwords are equal     puts("Is not the good password !");   }   else {     printf("Good work, the password is : \n\n%s\n",local_108c);   }   return; }</span>
</code></pre><p>That’s all!</p>
<p>Now we run the program. In other tools we just save the file and it works, but in Ghidra it seems that we need to export it.</p>
<p>To export the program, we go to File -&gt; Export Program (O). We change the format to binary and click OK.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/nQiTkhZ4S8BIG22V66wHKDDcovdTOugk1E3J" alt="Image" width="724" height="466" loading="lazy"></p>
<p>I get the exported program on my desktop but it doesn’t work — I couldn’t manage to run the exported program. After trying to read it’s header with the readelf -h program, I get the following output:</p>
<pre><code>root@DESKTOP:<span class="hljs-regexp">/mnt/</span>c/users/denis/Desktop# readelf -h Crack.bin ELF Header:   Magic:   <span class="hljs-number">7</span>f <span class="hljs-number">45</span> <span class="hljs-number">4</span>c <span class="hljs-number">46</span> <span class="hljs-number">01</span> <span class="hljs-number">01</span> <span class="hljs-number">01</span> <span class="hljs-number">00</span> <span class="hljs-number">00</span> <span class="hljs-number">00</span> <span class="hljs-number">00</span> <span class="hljs-number">00</span> <span class="hljs-number">00</span> <span class="hljs-number">00</span> <span class="hljs-number">00</span> <span class="hljs-number">00</span>   Class:                             ELF32   Data:                              <span class="hljs-number">2</span><span class="hljs-string">'s complement, little endian   Version:                           1 (current)   OS/ABI:                            UNIX - System V   ABI Version:                       0   Type:                              EXEC (Executable file)   Machine:                           Intel 80386   Version:                           0x1   Entry point address:               0x8048440   Start of program headers:          52 (bytes into file)   Start of section headers:          2848 (bytes into file)   Flags:                             0x0   Size of this header:               52 (bytes)   Size of program headers:           32 (bytes)   Number of program headers:         7   Size of section headers:           40 (bytes)   Number of section headers:         27   Section header string table index: 26 readelf: Error: Reading 1080 bytes extends past end of file for section headers</span>
</code></pre><p>Shame. It looks like Ghidra has messed up the <a target="_blank" href="https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header">file header</a>… and, right now I don’t want to manually fix headers. So I fired up another tool and applied the same patches to the file, saved it, ran it with a random argument and validated the flag.</p>
<h4 id="heading-conclusions">Conclusions</h4>
<p>Ghidra is a nice tool with a lot of potential. In its current state, it’s not that great but it works. I’ve also encountered a weird scrolling bug while running it on my laptop.</p>
<p>The alternatives would be to pay $$ for other tools of this kind, make your own tools, or work with free but not so user friendly tools.</p>
<p>Let’s hope that once the code is released, the community will start doing fixes and improve Ghidra.</p>
<p>Thanks for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How I Reverse Engineered A Chrome Extension To Write My Own Flask App ]]>
                </title>
                <description>
                    <![CDATA[ By Tushar Agrawal Basically, if I have no intention of using a service then I won’t bother reverse-engineering it. — Jon Lech Johansen As evident from my bio, I am crazy about music and pretty much anything related to it. And I believe that music v... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-i-reverse-engineered-a-chrome-extension-to-write-my-own-flask-app-d77f36421106/</link>
                <guid isPermaLink="false">66c34e0c0fa3812cdd5ea9f5</guid>
                
                    <category>
                        <![CDATA[ Google Chrome ]]>
                    </category>
                
                    <category>
                        <![CDATA[ chrome extension ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ reverse engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 02 Feb 2018 17:05:34 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*uOlxCoXq1faNmKA-3ie2Bg.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Tushar Agrawal</p>
<blockquote>
<p>Basically, if I have no intention of using a service then I won’t bother reverse-engineering it. — <em>Jon Lech Johansen</em></p>
</blockquote>
<p>As evident from my bio, I am crazy about music and pretty much anything related to it. And I believe that music videos, if well-directed, are possibly the best way to feel the inherent soul of music. </p>
<p>So, it all began with me watching the music video of a song “<strong>Heavydirtysoul</strong>” by <strong>Twenty One Pilots</strong>. The music video was so dope I didn’t even care for the lyrics. It was only after I listened to it a few times, I realized that I didn’t get much of the lyrics except the chorus part. </p>
<p>This is something that is an actual problem for many ESL (English as a Second Language) speakers. You can’t enjoy a song to its fullest if you don’t get the lyrics. </p>
<p>It was then that I thought of something: what if I could play the lyrics of a song alongside the music videos (much like subtitles)? It would be awesome if I could create subtitle files for my music videos and then play it on my video player!</p>
<h2 id="heading-initial-approach-and-finding-musixmatch">Initial Approach and finding Musixmatch</h2>
<p>I then began a comprehensive search for sites or APIs that could provide me the lyrics for a song. And as expected, I found a dozen sites that provided the lyrics. Cool… isn’t it? </p>
<p>Nah. Because, what I really needed was timed lyrics, much like a subtitle for a movie. I wanted the lyrics text to <strong>sync</strong> with the current video frame on the screen. After much searching, I was unable to find any such service.</p>
<p>It was only after a week someone told me to use <strong>Musixmatch</strong>, a chrome extension that embedded lyrics on YouTube videos. So, yeah, there was someone out there who was already doing what I had thought about. It sounded like most of the other well thought so-called new ideas I had...and I was just a step away from fetching SubRip “srt” subtitle files for my favorite music videos.</p>
<h3 id="heading-and-the-hacking-started">And the hacking started…</h3>
<p>I already had a bit of experience working with the chrome developer tools (thanks to Node.js and front end designing). So I put on my hacker glasses and fired up Chrome Dev tools. I switched to the network tab and began to look for any text file that could contain the lyrics.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*O89WdLDnoVHaOvXK5T-A5w.jpeg" alt="Image" width="800" height="342" loading="lazy">
<em>Snapshot of developer tools with YouTtube video playing</em></p>
<p>But I was analyzing requests on a page that was playing YouTube videos, so I had a plenty of requests. And since the extension was fetching lyrics, the request must have something to do with the Musixmatch domain. </p>
<p>So I filtered using the keyword ‘musix’ and looked patiently for my file and I finally found it. Lyrics along with the time stamp. I noted the URL of that request and frankly, it all seemed like gibberish to me. Anyways, I copied the URL string as such and then pasted it into the URL bar, and voilà, I got the lyrics. </p>
<p>So, the only thing left was to find out how the URL is being framed and what were the parameters..</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*JlKw3JsfgOuUkgG3SS0rRw.jpeg" alt="Image" width="800" height="107" loading="lazy">
<em>Request URL</em></p>
<h3 id="heading-parameters-and-what">Parameters and what?</h3>
<p>After all the analyzing and filtering, I finally ended up with this. A long URL with a bunch of unknown parameters.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*1kfqTsYqS8MjhQY5Dyqq0A.jpeg" alt="Image" width="755" height="239" loading="lazy">
<em>Parameters for the URL</em></p>
<p>I needed to dig deeper to actually understand the importance of each parameter. At a glance, it was clear that the only parameters that actually mattered were <code>res</code> and <code>v</code>. Others were just for house-keeping stuff. Then I began to explore the options and ended up wasting an hour just to find that the parameter <code>v</code> is nothing but the YouTube Video Id.</p>
<p>For example, the Video Id or <code>v</code> for a YouTube video with a URL https://www.youtube.com/watch?v=ZQeq_T_2VE8 is <code>ZQeq_T_2VE8</code>. Now that I had unveiled the mystery of <code>v</code>, I thought it would take me hardly another hour to find about <code>res</code>, but boy was I wrong.</p>
<h3 id="heading-the-curious-case-of-the-parameter-res">The curious case of the parameter ‘res’</h3>
<p>An hour of deep analysis and research gave me nothing. A little later, I realized that the URL worked even when I changed few alphabets. I kept up digging and by the end of the 3 hours, I figured out that the alphabets in the string didn’t mean anything. They were just put randomly.</p>
<pre><code>A typical value <span class="hljs-keyword">of</span> res : <span class="hljs-number">90</span>rt120b114xz70xv82w85vv90a94hn90vb102av86
</code></pre><p>So I was done with the alphabets but the numeric values were still alien to me. The next thing I could think of was applying a bit of reverse-engineering to analyze the numbers. </p>
<p>I began with removing all the alphabets as they didn’t mean anything and the first thing I noticed that the number of those values were fixed, the number being 11. I tried it with many other videos, but the number remained constant. </p>
<p>Suddenly, it struck me, Video Id, the <code>v</code>, we discussed earlier also had 11 characters. However, each character in <code>v</code> could be an alphabet or a digit or even a ‘-’ or ‘_’, unlike <code>res</code> which had only numbers. </p>
<p>So, I tried the most obvious mapping that can map a character to its numeric value, ASCII, and voilà that was it. The characters were ASCII encoded and alphabets were randomly put in between the numbers to make the whole string look more random, I guess.</p>
<p>At this point, I was delighted. After all, I had learned about all the parameters and was only a step away from writing my own handy script to download the lyrics file in “srt” format. Just to be sure, I checked with different videos and there seemed to be no issue whatsoever. I also shared the URL with one of my friends (yeah, a music lover).</p>
<p>I got a quick reply and it said “What is it? There’s nothing”. I crosschecked the URL and it was working fine on my browser.</p>
<h3 id="heading-who-was-the-culprit-p">Who was the culprit ? :P</h3>
<blockquote>
<p>I don’t get sent anything strange like underwear. I get sent cookies. :P — Jennifer Aniston</p>
</blockquote>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*zfKtWngPstlY9a7Iw64p3g.jpeg" alt="Image" width="800" height="302" loading="lazy">
<em>Cookie field in the Request Headers</em></p>
<p>I fired up the developer tools again and then copied the link for a new song. It again worked and then I switched to an incognito tab and pasted that same URL. It didn’t work. </p>
<p>My experience of CTF (Capture The Flag) contests immediately told me that it had something to do with the cookies. That’s the most likely case if a URL is working in a browser window and not the other. </p>
<p>I switched to the developer console and saw that the cookie was indeed being sent by the browser. To be sure, I analyzed the request many times and it finally occurred to me that the cookie being sent was the same the Musixmatch server is sending in the response. Also, each cookie is valid for only a certain time period. </p>
<p>So, I wrote a Python script using urllib that first gets the cookie from a normal HTTP response since the cookie works across the domain. Then the cookie along with other parameters was framed as an HTTP request and we got the lyrics... Finally!!</p>
<h3 id="heading-preparing-the-parameters-for-a-successful-request">Preparing the parameters for a successful request</h3>
<p>Here is the Python code for all the steps discussed above. The code first generates the parameters followed by a request to get the cookies. URL is then prepared using the parameters. Next, the cookie is defined in the header request along with other header fields like ‘Host’ and ‘User-agent’ to give it more of an authentic request look.</p>
<h3 id="heading-parsing-the-raw-timed-lyrics-into-srt-format">Parsing the raw timed lyrics into srt format</h3>
<p>Now, the next major thing or the only task left was to convert the raw timed lyrics data into a proper srt (SubRip Text) format. Here is what the MusixMatch lyrics format looked like.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*FcdBLOPuQQddd7uM6vYTrQ.jpeg" alt="Image" width="732" height="206" loading="lazy">
<em>HTTP Response for the lyrics</em></p>
<p>Below is a proper format for a srt file.These files contain formatted lines of plain text in groups separated by a blank line. Subtitles are numbered sequentially, starting at 1 as depicted in the figure below.</p>
<pre><code><span class="hljs-number">100</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00</span>,<span class="hljs-number">350</span> --&gt; <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">03</span>,<span class="hljs-number">45071</span> buildings explodedor caught fire.
</code></pre><pre><code><span class="hljs-number">200</span>:<span class="hljs-number">00</span>:<span class="hljs-number">03</span>,<span class="hljs-number">490</span> --&gt; <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">05</span>,<span class="hljs-number">020</span>Elliot, tell me what it isthat you think he did.
</code></pre><pre><code><span class="hljs-number">300</span>:<span class="hljs-number">00</span>:<span class="hljs-number">05</span>,<span class="hljs-number">060</span> --&gt; <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">06</span>,<span class="hljs-number">930</span>Sorry.I don<span class="hljs-string">'t know if I can say.</span>
</code></pre><p>This sounded like a whole lot of work was required as the data was yet to be properly formatted. But, if you have the required data and a knowledge of Python, all it takes is a simple script to handle the data and that’s exactly what I did. The HTML tags annoyed me a bit during HTML parsing but guess what, there is an awesome library just for HTML parsing which made the whole process very easy. No points for guessing the library’s name, HTMLParser :-).</p>
<h2 id="heading-final-words">Final words</h2>
<p>So, I put together this script along with some modifications and with a simple front end on a flask server, I had my own lyrics fetching interface, possibly the only one of its kind in the whole world !!</p>
<p>By the way, if you are into music, have a look at Musixmatch. It is really awesome. This exercise was just for educational purposes and wasn’t used in any way to violate Musixmatch’s copyright.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
