0% found this document useful (0 votes)
4 views

ASM2

The document discusses debugging programs using the GNU Debugger (GDB). It provides an overview of GDB and how it can be used to debug programs by stepping through code line-by-line, examining variable values, and identifying where programs crash. It also gives an example scenario where GDB is used to debug a bug in a macro processor program where macro definitions stop working when quote strings are changed.

Uploaded by

rameesarashid09
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

ASM2

The document discusses debugging programs using the GNU Debugger (GDB). It provides an overview of GDB and how it can be used to debug programs by stepping through code line-by-line, examining variable values, and identifying where programs crash. It also gives an example scenario where GDB is used to debug a bug in a macro processor program where macro definitions stop working when quote strings are changed.

Uploaded by

rameesarashid09
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 7

Life in the Real World Using the GDB Debugger

"In the dynamic realm of software development, debugging emerges as a critical


practice, allowing developers to uncover and rectify errors in their code. Among the
arsenal of debugging tools, the GNU Source-Level Debugger, commonly known as GDB,
stands out as a pivotal instrument. In this exploration, we delve into the practical
applications of GDB in real-world scenarios, shedding light on how developers harness
its capabilities to navigate the intricate landscape of identifying and resolving issues
within their code."

What is a debugger? : A debugger or debugging tool is a computer program used to


test and debug other programs. The main use of a debugger is to run the target
program under controlled conditions that permit the programmer to track its execution
and monitor changes in computer resources that may indicate malfunctioning code.

GNU Debugger : GNU Debugger, which is also called GDB, is the most popular
debugger for UNIX systems to debug C and C++ programs.

GNU Debugger helps you in getting information about the following:

 If a core dump happened, then what statement or expression did the program
crash on?

 If an error occurs while executing a function, what line of the program contains
the call to that function, and what are the parameters?

 What are the values of program variables at a particular point during execution of
the program?

 What is the result of a particular expression in a program?

How GDB Debugs? : GDB allows you to run the program up to a certain point, then
stop and print out the values of certain variables at that point, or step through the
program one line at a time and print out the values of each variable after executing each
line. GDB uses a simple command line interface.
Real-Life Scenario : One of the preliminary versions of gnu m4 (a generic macro
processor) exhibits the following bug:

sometimes, when we change its quote strings from the default, the commands used to
capture one macro definition within another stop working. In the following short m4
session, we define a macro foo which expands to 0000; we then use the m4 built-in
defn to define bar as the same thing. However, when we change the open quote string
to <QOUTE> and the close quote string to <UNQUOTE>, the same procedure fails to
define a new synonym baz:

Let us use GDB to try to see what is going on


Out-of-Bounds Memory References and Buffer Overflow

Buffer Overflow
A buffer is a sequential memory allocation or region that might hold anything from
integer arrays to character strings. The purpose of the buffer area is to hold program or
application data while it is being moved from one program to another, or between
sections of a program.

A buffer overflow happens when a program either tries to place data in a memory area
past the buffer, or attempts to put more data in a buffer than it can hold. Writing data
beyond an allocated memory block’s bounds can crash the program, corrupt data, or
allow an attacker to execute malicious code.

Buffer Overflow Attack : Buffer overflow attacks, well-known to developers, persist due
to various exploitation methods and error-prone prevention techniques. The clear
memory organization in systems, especially in features like buffers, creates
vulnerabilities, allowing attackers to seize privileges or inject malicious code.

Historical incidents and recent examples, like the 1988 Morris worm and attacks on
platforms like Steam, highlight the ongoing threat of buffer overflow techniques.

C and C++ programming languages, lacking built-in protections, make developers


susceptible to these attacks. Although bounds checking is possible, it adds complexity
and processing time. Safer operating systems use strategies like space layout
randomization and canaries.

In a classic scenario, an attacker overwrites a stack buffer, leading to the transfer of


control to malicious code upon function return. This type of stack buffer overflow is
common, along with other exploits like off-by-one errors, heap buffer overflows, and
format string attacks.

Prevent Buffer Overflow :

Assess buffer overflow vulnerability. First, determine if you are vulnerable. Stay
current with the latest bug reports for all libraries and server products.
Stay current. Protect your system infrastructure by updating with bug reports and
applying patches. Use a buffer overflow scanner to monitor your sites and applications
for security risks.

Safe libraries. Use of safe libraries is another tactic in preventing buffer overflow.
Standard library functions for the C and C++ languages expose your system to
overflows because they are not bounds checked. Well-tested and written libraries
centralize buffer management and perform it automatically, including bounds checking.

Buffer overflow testing tools. These tools vary, but their general goal is to detect
buffer overflows, identify their causes, and patch those weaknesses. Edge case testing,
fuzzing, and static analysis are all methods of automated buffer overflow testing.

Out of Bounds Memory References

Simply put, an “out of bound memory reference” is any read or write that is outside the
range of a defined structure. It can include (but is not limited to) writing 21 characters
into a 20 character string buffer; referencing index 21 in a 20 element array; or
referencing an uninitialized or discarded pointer.

Out-of-Bounds Read is a type of software error that can occur when reading data from
memory. This can happen if the program tries to read beyond the end of an array, for
example. Out of bounds reads can lead to crashes or other unexpected vulnerabilities,
and may allow an attacker to read sensitive information that they should not have
access to.

To avoid out-of-bounds reads, programs should check that the index they are using to
read data is within the bounds of the array. If it is not, the program should take some
other action, such as returning an error or printing a warning message.

If you are writing a program that might read data from memory, it is important to be
aware of this type of error and take steps to avoid it. Otherwise, your program may
crash or behave unexpectedly.

Out-of-Bounds Write is another type of software vulnerability in which a program


writes outside the bounds of an allocated area of memory, potentially leading to a crash
or arbitrary code execution. This can occur when the size of the data written is larger
than the size of the allocated memory area, when the data is written to an incorrect
location within the memory area, or when the program incorrectly calculates the size or
location of the data to be written.

Out-of-Bounds Write vulnerabilities can be exploited by an attacker to crash a program


or execute arbitrary code. In some cases, these vulnerabilities can beOut exploited to
overwrite critical program data structures, such as the heap control blocks, which can
lead to a denial-of-service attack. Other times, an attacker can use an out-of-bounds
write to modify program execution flow, such as by overwriting a function pointer or
return address on the stack, which can lead to arbitrary code execution.

To prevent out-of-bounds write vulnerabilities, programmers should carefully validate all


inputs to ensure that they fall within the expected range. Additionally, programs should
use memory safety features such as canaries or ASLR to make it more difficult for an
attacker to exploit these vulnerabilities.

x86-64 Extending LA32 to 64 Bits


The transition from x86-32 to x86-64 architecture represents a fundamental shift in
computer processing, primarily centered around the expansion of memory addressing
capabilities. In the x86-32 architecture, the processor could address a maximum of 4
gigabytes of memory, limiting the system's overall performance and capacity. The move
to x86-64, however, extends the address space to a staggering 18.4 million terabytes,
providing a significantly larger memory pool for applications to utilize.

One key advantage of x86-64 is the ability to handle larger datasets and more complex
calculations, making it particularly beneficial for memory-intensive tasks such as
scientific simulations, database management, and multimedia processing. The expanded
register space in x86-64 also enhances the efficiency of processing, allowing the CPU to
handle more data at once.

To facilitate the transition, software developers must update their applications to take
full advantage of the 64-bit architecture. This involves recompiling code, addressing
changes in data types and memory handling, and ensuring compatibility with existing
32-bit software.
Despite the advantages, backward compatibility remains crucial, as many legacy systems
and applications may still rely on the older x86-32 architecture. Therefore, modern
operating systems often provide a compatibility layer, allowing both 32-bit and 64-bit
applications to coexist on the same system.

In summary, the shift from x86-32 to x86-64 represents a leap forward in computing
capabilities, offering larger memory addressing, improved performance, and greater
efficiency. However, it necessitates careful consideration from developers to ensure a
smooth transition and continued compatibility with existing software.

Machine-Level Representations of Floating-Point Programs


Computers execute machine code, sequences of bytes encoding the low-level
operations that manipulate data, manage memory, read and write data on storage
devices, and communicate over networks.

To get the assembly output of the above C program (let's say it's in a pogram
named wawa.c), we use the following command:

gcc -Og -S wawa.c


In this command we instruct the gcc to output the files's assembly equivalent. -Og as
know prevents optimization. The assembly output should looks as follows:

You might also like