diff --git a/_labs/example_highlighting_guide.md b/_labs/example_highlighting_guide.md index ec4c098..59fddda 100644 --- a/_labs/example_highlighting_guide.md +++ b/_labs/example_highlighting_guide.md @@ -549,6 +549,76 @@ There is a flag to be found on a user's Desktop! Find and submit it to Hacktivit 8. **Improper command formatting**: Always use `bash` code blocks for terminal commands and escape pipe characters 9. **Uncapitalized block content**: Always capitalize the first word after "Note:", "Tip:", or "Hint:" since these labels are not visible in the rendered output +### Image Caption Formatting + +For proper CSS styling, image captions should be formatted as follows: + +**Format:** +```markdown +![][image_reference] +*Caption text here* +``` + +**Examples:** +```markdown +![][binary_output] +*Output of "xxd -b simple" showing binary representation of the "simple" executable file* +``` + +```markdown +![][assembly_code] +*Disassembly of main() function of the "simple" executable in gdb* +``` + +**Important Guidelines:** +- Place the caption on the line directly below the image (no blank line between) +- Use italics (`*text*`) for the caption +- Identify existing captions by looking for descriptive text that explains what the image shows (often incomplete sentences or phrases), rather than assuming any text following an image is a caption + +### C Code Formatting + +When working with C programming content, ensure all C code is properly formatted: + +**Format:** +```markdown +```c +// C code here +``` +``` + +**Important Guidelines:** +- Place any C code into C code blocks using ` ```c ` and ` ``` ` +- Remove any special characters from Markdown that may interfere with C syntax +- Ensure C code is syntactically correct and readable +- Common issues to fix: + - Remove escaped characters like `\*` and `\<` that were used for Markdown emphasis + - Remove backslashes before special characters that are part of C syntax + - Ensure proper C syntax without Markdown formatting artifacts + +**Examples:** + +**Before (incorrect):** +```markdown +\#include \ + +int main (void) { + printf("Hello, world\!\\n"); + return 0; +} +``` + +**After (correct):** +```markdown +```c +#include + +int main (void) { + printf("Hello, world!\n"); + return 0; +} +``` +``` + ### File Structure Requirements Ensure lab sheets maintain proper structure: @@ -558,6 +628,7 @@ Ensure lab sheets maintain proper structure: - **Working TOC** with functional anchor links - **Consistent code block formatting** using proper language tags - **Valid markdown syntax** throughout the document +- **Proper image caption formatting** using italics on the line directly below images --- diff --git a/_labs/introducing_attacks/1_intro_linux.md b/_labs/introducing_attacks/1_intro_linux.md index be8326c..f25f7ae 100644 --- a/_labs/introducing_attacks/1_intro_linux.md +++ b/_labs/introducing_attacks/1_intro_linux.md @@ -323,8 +323,7 @@ dhcpcd eth0 Virtualisation is a very powerful tool, which can provide important security features, such as isolation, and is an important component of many modern cloud infrastructures. Virtualisation can create virtual environments, and can even run entire operating systems as though they were on separate hardware. This type of virtualisation is known as platform virtualisation, or hardware virtualisation. As illustrated in the figure below, virtualisation allows one set of hardware (a computer), to host a number of guest virtual machines (VMs), each with their own operating systems, applications, and virtual hardware. ![Hardware Virtualization][virtualisation] - -Hardware Virtualization ([Image](http://commons.wikimedia.org/wiki/File:Hardware_Virtualization_\(copy\).svg): public domain by [John Aplessed](http://commons.wikimedia.org/wiki/User:John_Aplessed)) +*Hardware Virtualization ([Image](http://commons.wikimedia.org/wiki/File:Hardware_Virtualization_\(copy\).svg): public domain by [John Aplessed](http://commons.wikimedia.org/wiki/User:John_Aplessed))* During the module we will make use of various VMs to recreate realistic security scenarios, typically generated by our software and running on our oVirt and Proxmox cloud infrastructure. diff --git a/_labs/introducing_attacks/3_vulnerabilities.md b/_labs/introducing_attacks/3_vulnerabilities.md index 760f92f..7525abd 100644 --- a/_labs/introducing_attacks/3_vulnerabilities.md +++ b/_labs/introducing_attacks/3_vulnerabilities.md @@ -146,14 +146,12 @@ echo Good thing this isn't malware! > not_malware.txt The important thing to note is that with a bind shell the target listens to a port, and the attacker then connects through to the shell. This is illustrated below. ![Bind Shell Concept][bind_shell] - -Bind shell: attacker connects to port on victim +*Bind shell: attacker connects to port on victim* The main limitation with this approach, is that nowadays Firewalls and NAT routing often prevents any *incoming* network connections that are not already established, unless there is a reason to allow incoming connections on certain ports: for example, if the system is a server it needs to be allowed to accept connections to some ports. Score one for the good guys... ![Bind Shell Blocked by Firewall][bind_shell_blocked] - -Bind shell: main limitation, NAT/firewalls rules typically prevent this +*Bind shell: main limitation, NAT/firewalls rules typically prevent this* When you are finished simulating a bind shell, run: @@ -164,8 +162,7 @@ exit A solution for an attacker is to rethink the way the connection is established; and rather than connect from the attacker to the victim, get the victim to initiate the connection to the attacker. This is known as a *reverse shell*, and is now the most common approach to shell payloads. ![Reverse Shell Concept][reverse_shell] - -Reverse shell: connection from the victim to the attacker +*Reverse shell: connection from the victim to the attacker* Again, you will simulate this using Netcat: @@ -222,8 +219,7 @@ Metasploit’s primary focus, as the sound of the name suggests, is on exploits, The framework itself provides a set of libraries and tools for exploit development and deployment, and includes modules which add support for specific exploits, payloads, encoders, post-exploitation tools, and other extensions. As illustrated in the figure below, sitting above the framework are a number of different interfaces that can be used to interact with the framework and make use of the modules. Each interface has its uses, and like many software tools, you should learn about the available options so that you can use the right tool for each job. ![Metasploit Interfaces and Modules][msf_interfaces] - -Metasploit interfaces and modules +*Metasploit interfaces and modules* The most popular interfaces for MSF are: diff --git a/_labs/introducing_attacks/5_scanning.md b/_labs/introducing_attacks/5_scanning.md index 9a563c7..b418260 100644 --- a/_labs/introducing_attacks/5_scanning.md +++ b/_labs/introducing_attacks/5_scanning.md @@ -376,7 +376,7 @@ less ==edit:IP-address==.open_ports Many port scanners are quite simple, and do more than is strictly necessary to know whether a port is open. In order to establish a TCP connection and start sending and receiving data, a full three way handshake takes place. ![][tcp_handshake] -TCP three-way handshake +*TCP three-way handshake* As illustrated above, 1\) the client starts by sending a TCP packet that includes the port that it wants to talk to (say port 80), and the SYN flag set, meaning that it wants to start a new connection. 2\) If the server accepts the connection (there is indeed a program listening on that port), then it responds with the SYN and ACK flags set, meaning it accepts the connection. 3\) The client can now complete the connection by sending a packet with the ACK flag set. @@ -650,8 +650,7 @@ Based on what you have learned: There are various graphical user interface (GUI) front-ends for Nmap, including the official Zenmap, which is illustrated in the figure below. Essentially the GUI can help to create the command for starting Nmap, and then runs Nmap and displays the results. The GUI can be helpful for beginners, and for saving scanning profiles, although most experts will generally prefer the command line. ==tip: Consider why the command line may be the preferable option==. ![][zenmap] - -[Zenmap: a GUI for Nmap](http://nmap.org/zenmap/) +*[Zenmap: a GUI for Nmap](http://nmap.org/zenmap/)* > Note: Kali Linux recently removed Zenmap (and all python 2 programs), however, the screenshot above illustrates that these GUI programs provide an alternative interface. If you wish to learn more about it, you can find information at [https://nmap.org/zenmap/](https://nmap.org/zenmap/). You could also spend a few minutes looking into alternative GUIs. diff --git a/_labs/introducing_attacks/6_exploitation.md b/_labs/introducing_attacks/6_exploitation.md index 1ecd588..024a566 100644 --- a/_labs/introducing_attacks/6_exploitation.md +++ b/_labs/introducing_attacks/6_exploitation.md @@ -100,8 +100,7 @@ For many, the Metasploit framework (MSF) is the tool of choice when it comes to The result is a free and open source[^1] framework, which now includes over a thousand different exploits. Other exploit frameworks for penetration testing include Core Impact (much more expensive, but similar power to Metasploit) and Canvas (also popular with some businesses, with hundreds of exploits). ![][metasploit_launch_slide] - -The presentation that introduced Metasploit +*The presentation that introduced Metasploit* Given how powerful MSF is, it is helpful to know how to get scan results into Metasploit, how to conduct scanning from within Metasploit itself and, based on these results, search for and launch attacks. @@ -435,8 +434,7 @@ Based on the operating system and service detection, Armitage can suggest attack ==action: Under the attack menu for the VM (the popup you were just looking at), click "ftp", and "easyftp_cwd_fixret". Click "launch".== ![][armitage_attack_menu_easyftp] - -Launching an automatically suggested attack in Armitage +*Launching an automatically suggested attack in Armitage* Voila! The screen will be shown in red. You have exploited a vulnerability in the system, and now have administrator access to the server, meaning you can run commands on the remote computer! diff --git a/_labs/introducing_attacks/7_post-exploitation.md b/_labs/introducing_attacks/7_post-exploitation.md index c4f7d25..ec7f354 100644 --- a/_labs/introducing_attacks/7_post-exploitation.md +++ b/_labs/introducing_attacks/7_post-exploitation.md @@ -102,7 +102,7 @@ In any of these cases, this is *almost* the same thing as having normal physical > Note: An Nmap scan detects the distccd service running on port 3632. ![][nmap_distcc] -Nmap showing distccd port open +*Nmap showing distccd port open* You will recall from the previous Vulnerabilities lab that [Distcc](http://distcc.googlecode.com/svn/trunk/doc/web/index.html) is a network service to distribute software compilation across multiple computers on a network. A search of the Metasploit database reveals that there are security issues with distccd. ==action: Run:== @@ -127,7 +127,7 @@ msf > info exploit/==edit:name== > Hint: "use *exploit*", "show payloads", "set payload *payload*", "show options", "set *option value*", "exploit". Don't forget to set the IP address, when setting the options. A good payload would be "cmd/unix/reverse". ![][msf_set_rhost_exploit] -Shell access on the Linux server +*Shell access on the Linux server* > Note: Although you will not be greeted with a command prompt, you should now have shell access. ==action: Confirm you have shell access to the target Linux server system. Run:== @@ -510,12 +510,10 @@ sudo armitage & ==action: Add and scan the Windows host. (Hint: Hosts, Add Host, enter IP address. Right click the host icon, and click Scan.)== ![][armitage_add_hosts] - -Adding a host to Armitage +*Adding a host to Armitage* ![][armitage_scan] - -Running various MSF scans on a host in Armitage +*Running various MSF scans on a host in Armitage* At this point, you could instruct Armitage to "Find Attacks", but lets simply launch the EasyFTP exploit, which we know from previous experience the system is vulnerable to. @@ -530,14 +528,12 @@ At this point, you could instruct Armitage to "Find Attacks", but lets simply la > Note: The attack worked, as indicated by the red icon with lightning bolts. One of the greatest features of Armitage is that it shows you msfconsole, and all the MSF commands it is issuing. Also, take note of the fact that the "exploit" tab showing what MSF is doing, shows that a Meterpreter session has been opened. ![][armitage_meterpreter_session_created] +*Armitage exploitation with the Meterpreter payload* -Armitage exploitation with the Meterpreter payload - -> Note: Scroll up, and read through the msfconsole tab for the exploit, and note that the payload used was Meterpreter, rather than a bind or reverse shell. Meterpreter is an advanced payload, originally developed by Matt Miller, AKA Skape. Meterpreter has lots of advanced features that are helpful for an attacker (such as spyware, and various system commands), and is dynamically extensible, meaning that features can be added as needed. By default Meterpreter encrypts traffic between the attacker and the compromised host. +Scroll up, and ==action:read through the msfconsole tab for the exploit==, and note that the payload used was Meterpreter, rather than a bind or reverse shell. Meterpreter is an advanced payload, originally developed by Matt Miller, AKA Skape. Meterpreter has lots of advanced features that are helpful for an attacker (such as spyware, and various system commands), and is dynamically extensible, meaning that features can be added as needed. By default Meterpreter encrypts traffic between the attacker and the compromised host. ![][armitage_interact_meterpreter_menu] - -Interacting with a Meterpreter shell in Armitage +*Interacting with a Meterpreter shell in Armitage* ==action: Open an interactive Meterpreter tab (right click the Windows icon, select Meterpreter, Interact, Meterpreter Shell)==. @@ -572,8 +568,7 @@ meterpreter > ls c:/ Armitage also has a nice file browser, which you may like to explore. ![][armitage_browse_files] - -Browsing files on the victim system +*Browsing files on the victim system* ==action: Meterpreter can be used to easily gather hashes of passwords:== @@ -584,8 +579,7 @@ meterpreter > run post/windows/gather/hashdump Armitage also provides a frontend for this feature, which you should try[^1]. ![][armitage_dump_hashes] - -Dumping password hashes with Armitage +*Dumping password hashes with Armitage* You can also view a list of all the processes running: @@ -600,8 +594,7 @@ Or via Armitage, as shown in the figure below. Note the PID of a long-term process. ![][armitage_meterpreter_show_processes] - -Listing processes +*Listing processes* Metasploit tries to avoid leaving forensic evidence. It remains in memory, and generally does not write to disk. By default it will hide itself as an "svchost.exe" process, which is a normal component on a Windows system (it hosts various services). Metasploit can also migrate between processes, by injecting itself into another running program. @@ -634,8 +627,7 @@ Meterpreter also has “spyware” features, such as the ability to monitor the ==action: Set the CAPTURE_TYPE option to "winlogon", and click Launch==. ![][armitage_launch_keylog] - -Keylogging user logins on a Windows target +*Keylogging user logins on a Windows target* > Tip: *If the system had active users, you would see all that they type.* @@ -662,14 +654,12 @@ Usually a command line (standard shell or Meterpreter) is the most effective way ==action: Right click the Windows host icon, and click Meterpreter, Interact, Desktop (VNC)==. ![][armitage_vnc] - -Starting a VNC server on the target system +*Starting a VNC server on the target system* > Note: Note the IP address and port Armitage tells you to connect to. ![][armitage_vnc_running_ip_and_port] - -Armitage information about the VNC server to connect to +*Armitage information about the VNC server to connect to* ==action: From a Kali Linux bash prompt, run:== @@ -678,8 +668,7 @@ vncviewer 127.0.0.1:port ``` ![][armitage_vnc_desktop] - -VNC viewer accessing the desktop of a compromised system +*VNC viewer accessing the desktop of a compromised system* Experiment with this feature. It is also possible to configure VNC to only view the remote system, without taking control of the mouse and keyboard. @@ -713,23 +702,22 @@ At this point you can route almost any traffic via your compromised host, includ > Warning: If Armitage takes a very long time to pivot these attacks, feel free to skip this section. You can look at the screenshots below to see what this interaction looks like when successful. -> Note: The Armitage interface illustrates that our attacks against the Linux Server VM are sent via the Windows system. +The Armitage interface illustrates that our attacks against the Linux Server VM are sent via the Windows system. ![][armitage_pivot] +*A pivot routing all attacks against the system displayed on the right through the system on the left* -A pivot routing all attacks against the system displayed on the right through the system on the left - -> Note: Now, any attacks we launch at this system will be proxied through the Windows VM. +Now, any attacks we launch at this system will be proxied through the Windows VM. > Flag: **Exploit a vulnerability in the Linux Server VM via the Windows VM.** -> Note: *You may need to troubleshoot the pivoting setup, if you experience issues. You can skip this step, if you feel you understand the concept and advantages.* +> Tip: *You may need to troubleshoot the pivoting setup, if you experience issues. You can skip this step, if you feel you understand the concept and advantages.* > Question: Consider the advantages of pivoting for an attacker. ## What else would an attacker want to do? {#what-else-would-an-attacker-want-to-do} -> Note: Other common steps include attempting to maintain access, so that a server restart would not require the attacker to exploit the vulnerability again, and covering their tracks, so that log files, and disk contents, do not indicate an attack has taken place. You may wish to investigate these further, especially in relation to features of Meterpreter. +Other common steps include attempting to maintain access, so that a server restart would not require the attacker to exploit the vulnerability again, and covering their tracks, so that log files, and disk contents, do not indicate an attack has taken place. You may wish to investigate these further, especially in relation to features of Meterpreter. > Question: Experiment with Armitage and Meterpreter to cover your tracks after an attack, and persist so that you maintain access. diff --git a/_labs/software_and_malware_analysis/1_dynamic_and_static_analysis.md b/_labs/software_and_malware_analysis/1_dynamic_and_static_analysis.md index 71b6a2b..3491873 100644 --- a/_labs/software_and_malware_analysis/1_dynamic_and_static_analysis.md +++ b/_labs/software_and_malware_analysis/1_dynamic_and_static_analysis.md @@ -1,6 +1,6 @@ --- title: "Introduction to Dynamic and Static Analysis" -author: ["Z. Cliffe Schreuders"] +author: ["Z. Cliffe Schreuders", "Tom Shaw"] license: "CC BY-SA 4.0" description: "Learn fundamental malware analysis techniques including static and dynamic analysis of binary executables, and reverse engineering." overview: | @@ -71,8 +71,7 @@ cat /bin/ls Scroll up, and you can see that there is some human readable text, but mostly the values can’t even be clearly represented in a readable way. That’s because standard tools such as cat (and most text editors) assume a human-readable format such as ASCII (American Standard Code for Information Interchange), which represents each printable character as a value. ![][ascii_table] - -[https://commons.wikimedia.org/wiki/File:Ascii-proper-color.svg](https://commons.wikimedia.org/wiki/File:Ascii-proper-color.svg) +*ASCII table showing character codes and their hexadecimal representations [https://commons.wikimedia.org/wiki/File:Ascii-proper-color.svg](https://commons.wikimedia.org/wiki/File:Ascii-proper-color.svg)* However, executable binary files are actually made up of machine code instructions, which include many values that are not in these standard printable ranges, and interpreting these instructions as ASCII (as with the cat output) for the most part does not provide meaningful information. @@ -89,8 +88,7 @@ hexdump /bin/ls ``` ![][hex_dump] - -Output of hexdump showing offsets and file contents in hexadecimal format +*Output of hexdump showing offsets and file contents in hexadecimal format* Note that the output includes the hexadecimal memory address (offset from the start of the file), and the file contents displayed in hexadecimal format. @@ -144,12 +142,12 @@ The ELF file is organised, starting with an ELF header (describing things such a * .rodata: constant data, such as strings ![][elf_sections] - -[https://en.wikipedia.org/wiki/File:Elf-layout--en.svg](https://en.wikipedia.org/wiki/File:Elf-layout--en.svg) +*ELF file structure showing different sections and their purposes [https://en.wikipedia.org/wiki/File:Elf-layout--en.svg](https://en.wikipedia.org/wiki/File:Elf-layout--en.svg)* Have a look at this visualisation: [![][elf_walkthrough]](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#/media/File:ELF_Executable_and_Linkable_Format_diagram_by_Ange_Albertini.png) +*Detailed ELF file format diagram showing the complete structure* [Click here to view this useful visualisation larger.](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#/media/File:ELF_Executable_and_Linkable_Format_diagram_by_Ange_Albertini.png) @@ -248,7 +246,7 @@ As previously mentioned, system software is typically developed using a high-lev Very few people directly work with machine code in a binary or hex view, since this is almost indecipherable for a human; it is much more intuitive to view the instructions in an executable file as assembly code. Assembly language describes the low level instruction steps for a CPU using (*many*) short lines of code representing machine code instructions. At one point in history (before the 1980s) Assembly was the primary way that program code was written. The figure below shows an example of compiled machine code (such as “B9FFFFFFFF”) and the assembly that describes the instruction (“mov ecx, \-1”). In this case, this instruction sets the ECX CPU register to the value “-1”, which is clearly easier to understand in the assembly code rather than the machine code that the computer runs. ![][hex_asm_description] -Example machine code, and corresponding assembly code, and description[^1] +*Example machine code, and corresponding assembly code, and description[^1]* There are various programs, known as disassemblers, that can be used to display an executable file’s instructions, as assembly code. @@ -355,4 +353,4 @@ This sets the stage nicely for learning about reverse engineering, and the impor [elf_sections]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/1_dynamic_and_static_analysis/elf_sections.png [elf_walkthrough]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/1_dynamic_and_static_analysis/elf_walkthrough.png [hex_asm_description]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/1_dynamic_and_static_analysis/hex_asm_description.png -[hex_dump]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/1_dynamic_and_static_analysis/memory_hex_contents.png +[hex_dump]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/1_dynamic_and_static_analysis/hex_dump.png diff --git a/_labs/software_and_malware_analysis/2_intro_to_c.md b/_labs/software_and_malware_analysis/2_intro_to_c.md new file mode 100644 index 0000000..45ba1d4 --- /dev/null +++ b/_labs/software_and_malware_analysis/2_intro_to_c.md @@ -0,0 +1,744 @@ +--- +title: "Introduction to C Programming" +author: ["Thalita Vergilio", "Tom Shaw", "Z. Cliffe Schreuders"] +license: "CC BY-SA 4.0" +description: "Learn fundamental C programming concepts including data types, arrays, strings, conditionals, loops, functions, and pointers for malware analysis." +overview: | + In this lab, you will dive into the world of the C programming language, exploring its fundamental concepts and practical applications. Understanding C is essential, not only for programming but also for dissecting and analyzing malware, as many malicious programs are still written in C due to its low-level control over system resources. The lab begins by differentiating between high and low-level languages, highlighting the importance of assembly language and its human-readable representation. It emphasizes that, while you'll be working with high-level languages like C, you should be aware of the low-level details, which will be crucial for future tasks in the realm of cybersecurity. + + Throughout the lab, you will learn the basics of C programming by working on hands-on exercises. You'll start by creating a simple "Hello, world!" program, and then progress to explore data types, arrays, strings, conditionals, loops, functions, and pointers. For instance, you will write code to calculate averages and VAT, work with pointers to access memory addresses, and understand the relationship between arrays and pointers. By the end of this lab, you will have gained practical experience in C programming, setting a solid foundation for future endeavors in the field of cybersecurity and malware analysis. + +tags: ["c-programming", "low-level-programming", "memory-management", "pointers", "malware-analysis", "reverse-engineering"] +categories: ["software_and_malware_analysis"] +lab_sheet_url: "https://docs.google.com/document/d/14kz_ZD6UyrfeBMc2o0obPv1zrkv023_1jjbTrbJVP-k/edit?usp=sharing" +type: ["ctf-lab", "lab-sheet"] +difficulty: "intermediate" +cybok: + - ka: "MAT" + topic: "Technical Underpinning" + keywords: ["Technical underpinnings for malware analysis: C"] +--- + + +## Introduction + +Although malware can be written in any language, the vast majority is still written in C, as this language offers developers unparalleled control of the computer's memory and resources. This week, we will cover basic C programming. We will learn to write, compile and run C programs in preparation for disassembling them next week. + +## High and low level languages {#high-and-low-level-languages} + +When you run a program on your computer, what your CPU does behind the scenes is read and execute a number of machine language instructions. Ultimately, computers process zeros and ones, which is why machine code is represented in binary. Binary instructions however are very difficult for humans to read and comprehend. Can you make any sense of the instructions below? + +![][image-2] +*Output of “xxd \-b simple” showing binary representation of the “simple” executable file* + +Assembly language is a human-readable way of representing machine code. It uses mnemonics to represent instructions that the CPU executes, such as “push”, “mov” and “call”. Look at the assembly code below, is it not slightly more human-friendly? Don’t worry about trying to understand what it does for now. By the end of this module, you will be able to follow assembly instructions like these to work out what the code is doing. + +![][image-3] +*Disassembly of main() function of the “simple” executable in gdb* + +Both assembly language and machine code are low level languages. For each instruction in machine code, there is exactly one instruction in assembly language. You can think of assembly language as a human-friendly way of representing the binary instructions that the processor executes, which is why it is so important to be able to understand it when you are analysing malware. + +Assembly language and machine code are architecture-specific, so code that runs on one type of CPU architecture such as X86 will not run on another type, such as ARM. Since X86 is the most common type of CPU architecture used in personal computers, we are going to focus on it during this module. + +Although it is not common to write programs directly in assembly language nowadays, particularly given the power and complexity of modern CPUs and programs, assembly language is still used by developers looking to achieve maximum utilisation or full control of the processor’s behaviour such as, for example, when working with micro-devices. + +![][image-4] + +The diagram above shows how an assembler converts assembly instructions written by a developer into machine code which a computer can execute. Since the assembly instructions have a one-to-one relationship with machine code instructions, this is a simple conversion to make. As a malware analyst, you should note that it is also just as simple to reverse the process and convert machine code into assembly code which you can read. + +![][image-5] + +> Question: If humans can read and write assembly code, why do we need high-level languages? + +If you have some programming experience, it is likely that you are familiar with languages operating at a much higher level of abstraction such as Java, C++ or Python. These are called high-level languages. They are architecture-agnostic, so the code is written the same way regardless of the architecture used to execute it. High-level languages abstract a great number of instructions away from the developer, who typically does not care about where the stack pointer is during the program’s execution, or whether certain registers have been populated before a function is called. + +![][image-6] + +The figure above shows the typical process of compiling source code written in a high-level language into machine code that the computer can execute. + +> Question: How about interpreted languages, how are they different from compiled languages? + +C is a high-level language. It does however offer developers great control over low-level features such as memory allocation and garbage collection. Modern reverse-engineering tools such as IDA-Pro and Ghidra usually go beyond disassembly and provide an attempt at reconstructing the source code. The language used is C, since it can most accurately represent the low-level instructions contained in the executable. If a different high-level language were to be used for the reconstruction, it would probably leave out a lot of the instructions contained in the assembly code, some of which could be crucial for you as a malware analyst. + +Remember the assembly code we were looking at at the start? Here is the source code, in C. Isn’t it much easier to read now? + +![][image-7] +*Source code of the "simple" executable* + +## Getting started with C {#getting-started-with-c} + +> Note: You may have noticed that this week's lab is a little different. There are no flags to capture, although you should still attempt the programming exercises suggested. + +The code we are writing this week is very simple, and the exercises can all be solved using the vi text editor and gcc compiler provided in this week’s VM. Since there are no flags in the actual VMs, however, you could choose to write your code on your desktop or a development environment of your choice. It is entirely up to you. If you prefer to use an IDE, go ahead and pick one you like. IDEs are generally recommended for larger, more complex projects, but it is fine to use them if you find that they suit your learning style better. + +### Hello world + +Let’s start this week’s lab with a very simple “hello world” program in C. + +==action: Open a terminal in your VM and type:== + +```bash +vi hello-world.c +``` + +==action: Press the "i" key to enter "insert mode".== + +==action: Enter and save this content (Ctrl + Shift + V to paste):== + +```c +#include + +int main (void) { + printf("Hello, world!\n"); + return 0; +} +``` + +==action: Press the "ESC" key to exit "insert mode".== + +==action: Now to quit and save the file press the ":" key, followed by "wq" (write quit), and press Enter.== + +==action: Let's compile our program using gcc. Type:== + +```bash +gcc hello-world.c -o hello-world +``` + +> Note: How you now have two files, the source code and the executable file. + +==action: To run it, type:== + +```bash +./hello-world +``` + +![][image-8] + +Did you get the same output? + +### Hello world with runtime argument + +Now that we have written our first C program, let's see if we can make it a little more interesting. ==action: Change the code slightly to capture a string argument passed in when the program is run:== + +```c +#include + +int main (int argc, char *argv[]) { + printf("Hello, %s!\n", argv[1]); + return 0; +} +``` + +==action: Compile your program.== + +==action: To run the program with a runtime argument, type:== + +```bash +./hello-world Thalita +``` + +![][image-9] + +Note how the main function’s signature changed to accept two arguments: an int and an array of character pointers. We will look at pointers in more detail later on so, for now, just think of argv as an array of strings. In C, there are two accepted signatures for the main function, one which takes no arguments (void) and the one which you used in this example. + +Let’s take a closer look at the printf() function. Note how the “%s” placeholder is used to indicate where to insert the string passed to the program at runtime. Note also how the runtime argument is accessed as argv\[1\]. Arrays in C are zero-based. + +> Question: What does argv[0] contain? + +> Question: Change the code so it accepts two arguments and prints your name and surname. + +![][image-10] +*Example output showing two arguments being passed to the program* + +## Variables and data types {#variables-and-data-types} + +C is a strongly-typed language. Effectively, this means that, when you declare a variable to store a value of a certain type, you can’t later use it to store a value of a different type. There are four basic type specifiers in C: char, int, float and double. Their sizes are: + +* char 1 byte (8 bits) +* int 4 bytes (32 bits) +* float 4 bytes (32 bits) +* double 8 bytes (64 bits) + +> Tip: It will really help to memorise the basic data types above and their sizes since we will use them throughout the module. + +The basic data types can be used in conjunction with the modifiers: signed, unsigned, short and long, which modify how much space is allocated to each type. + +> Question: How large is a long int, in bytes? How about a short int? Consider writing a short program to find out. + +==action: Let's write some code to familiarise ourselves with these data types.== + +==action: Create a file called data-types.c and enter the following code:== + +```c +#include +int main (int argc, char *argv[]) { + int quantity = 12; + short size = 'S'; + float price = 2.85; + double total = price * quantity; + + printf("I bought %d size %c coffees. \n", quantity, size); + printf("They cost £%f each. \n", price); + printf("I paid a total of £%f. \n", total); + + return 0; +} +``` + +==action: Compile and run your code.== + +Look at the different format specifiers for printf(): + +[https://www.tutorialspoint.com/c\_standard\_library/c\_function\_printf.htm](https://www.tutorialspoint.com/c_standard_library/c_function_printf.htm) + +> Question: Can you find a way of printing the float and double values neatly, without the trailing zeroes? + +> Action: Try modify the first printf statement so that, instead of coffee, you are buying whatever is specified at runtime. + +![][image-11] +*Example output showing data types and their values* + +You can assign binary, octal or hexadecimal literals to integer variables by using the prefixes 0b (for binary), 0 (for octal) and 0x (for hexadecimal). So, for example, the number 26 in decimal could be assigned as 0b11010, 032 or 0x1a. + +All of these give the same resulting value (26): + +* int quantity \= 26; +* int quantity \= 0b11010; +* int quantity \= 032; +* int quantity \= 0x1a; + +*If you are not familiar with converting numbers between bases, or if it’s been a while since you learned it, here is a good 16min video to brush up your knowledge:* + +[*Number Systems \- Converting Decimal, Binary and Hexadecimal*](https://youtu.be/aW3qCcH6Dao) + +> Action: Update your code to initialise (initially set) the quantity variable with a hexadecimal value instead of decimal. + +> Action: Do the same, but this time give it a binary value. + +> Action: Observe that the output is the same in both cases. + +## Arrays {#arrays} + +Arrays are data structures used to store a predetermined number of elements of the same type. Since the elements of an array are stored next to each other in memory, once declared, an array cannot be extended or reduced in size. You can, however, modify the elements that are stored in it. The syntax for declaring and accessing elements of an array in C is similar to other high-level languages. In fact, you have been using arrays already. Go back a few steps and look at how you accessed the argv variable containing values passed to the program at runtime. + +Let's write some code to practice working with arrays. + +==action: Create a file called arrays.c and enter the following code:== + +```c +#include + +int main(int argc, char *argv[]) { + int numbers[3]; + numbers[0] = 1; + numbers[1] = 2; + numbers[2] = 4; + + printf("The sum of all %d integers is %d.\n", sizeof(numbers)/sizeof(int), numbers[0] + numbers[1] + numbers[2]); + return 0; +} +``` + +==action: Compile and run your code.== + +> Question: Can you replace the first four lines of the main function with a one-line initialiser? + +> Tip: Ensure you understand the line of code that starts with printf, just above the return statement. + +### Strings {#strings} + +Sorry to break the news to you, but there are no strings in C. That’s right, the concept of a string in other high level languages is an abstraction that does not really exist in C. So how can we represent the word “hello” in C? Well, all we need to do is store the characters ‘h’, ‘e’, ‘l’, ‘l’ and ‘o’ next to each other in memory, right? So we use an array of characters. + +Let's check it out with some code. + +==action: Create a file called strings.c and enter the following code:== + +```c +#include + +int main(int argc, char *argv[]) { + char word [5]; + word[0] = 'h'; + word[1] = 'e'; + word[2] = 'l'; + word[3] = 'l'; + word[4] = 'o'; + + printf("The word is: %c%c%c%c%c.\n", word[0], word[1], word[2], word[3], word[4]); + return 0; +} +``` + +==action: Compile and run your code.== + +Yes, it works. But how incredibly verbose and time-consuming\! Luckily, because arrays of characters are so common, there are some shortcuts we can use. + +==action: Replace the code above with the following:== + +```c +#include + +int main(int argc, char *argv[]) { + char word [5] = "hello"; + printf("The word is: %s.\n", word); + return 0; +} +``` + +Much better, don’t you think? Now, if you run it, you might notice something odd happening after the word “hello” is printed. What is going on there? What are these funny characters? + +![][image-12] + +Since a string is just an array, and arrays are just a bunch of spaces in memory used contiguously, the printf function does not know when to stop printing. If there is something else using the space in memory right next to the last character of your word, it will print that too, and will carry on printing. To prevent this behaviour, functions that deal with strings conventionally look for the null terminator ‘\\0’ in an array of characters. In fact, the shortcut you used in the previous exercise to assign the value “hello” to the word array already takes care of that. If you change the array size to 6, you will see that the null terminator is now added for you, and the string is printed correctly. + +```c +#include + +int main(int argc, char *argv[]) { + char word [6] = "hello"; + printf("The word is: %s.\n", word); + return 0; +} +``` + +![][image-13] + +Note that, if you are populating the array manually as we did in the first exercise, you will have to add the null terminator yourself. + +```c +#include + +int main(int argc, char *argv[]) { + char word [6]; + word[0] = 'h'; + word[1] = 'e'; + word[2] = 'l'; + word[3] = 'l'; + word[4] = 'o'; + word[5] = '\0'; + + printf("The word is: %s.\n", word); + return 0; +} +``` + +## Conditionals {#conditionals} + +Conditional statements are a fundamental part of any programming language. Without conditional statements, all instructions would have to be executed in sequence, regardless of what happened at runtime. As an example, a very simple program to look for your missing house keys could be: “Look on the kitchen counter. If they are there, stop. If not, look under the bed. If they are there, stop. If not, check if the dog has eaten them. If the dog has eaten them, wait 24h. If not, call the locksmiths and change the lock.” Without conditional statements, your program would look in all places, wait 24h, call the locksmiths and change the locks \- even if the keys happened to be under the bed\! + +C uses “if” and “switch” statements for making decisions based on conditions that evaluate to true or false. Let’s check how both of these work by writing some code: + +==action: Create a file called conditionals.c and enter the following code:== + +```c +#include + +int main(int argc, char *argv[]) { + if (argc == 1) { + printf("You haven't entered any arguments.\n"); + } else if (argc > 1 && argc < 3) { + printf("Your argument is: %s\n", argv[1]); + } else { + printf("You entered too many arguments.\n"); + } + return 0; +} +``` + +==action: Compile and run your code.== + +==action: Test the three possible execution paths.== + +![][image-14] + +==action: Change the “else if” condition to something less verbose.== + +==action: Change the program so that it prints up to three arguments.== +> Aim for the output below: + +![][image-15] + +You may have noticed that your code can quickly become quite verbose when there are too many if statements involved. Switch statements can be used in C (as in other high-level programming languages) to successively compare a value to a number of other values. The syntax for a switch statement is: +```c +switch (expression) { + case constant: + statement; + break; + + case constant: + statement; + break; + default : + statement; +} +``` + +Note that the breaks are optional, as is the default statement. Let’s rewrite the code from the previous exercise using a switch statement. + +```c +#include + +int main(int argc, char *argv[]) { + switch (argc) { + case 1: + printf("You haven't entered any arguments.\n"); + break; + case 2: + printf("Your argument is: %s\n", argv[1]); + break; + case 3: + printf("Your arguments are: %s and %s\n", argv[1], argv[2]); + break; + case 4: + printf("Your arguments are: %s, %s and %s\n", argv[1], argv[2], argv[3]); + break; + default : + printf("You entered too many arguments.\n"); + } + return 0; +} +``` + +> Question: What happens if you remove the breaks? + +==action: Create a file called fallthrough.c and enter the following code:== + +```c +#include + +int main(int argc, char *argv[]) { + if (argc == 1) { + printf("You haven't entered any arguments.\n"); + return 1; + } else if (argc > 4) { + printf("You have entered too many arguments.\n"); + return 1; + } + printf("Your arguments are:"); + switch (argc) { + //TODO: ADD YOUR CODE HERE + } + return 0; +} +``` + +==action:Implement the switch statement above using fallthrough to achieve the outcome below.== + +![][image-16] + +## Loops {#loops} + +Loops are used in programming languages to execute statements repeatedly until some condition is met (or sometimes infinitely). There are three types of loops in C: the “for loop”, the “while loop” and the “do while loop”. They are similar to loops you may have encountered in other programming languages. + +A typical for loop has three elements: initialisation, test and increment. + +```c +for (int i = 0; i < 10; i++) { + + printf("%d\n", i); + +} +``` + +The printf function is called 10 times in the example above, printing the numbers 0-9. + +All three elements are optional. + +> Question: What happens when you run the code below? + +```c +#include + +int main (int argc, char *argv[]) { + for (; ; ) { + printf("%d\n", 0); + } +} +``` + +The while loop is similar to the for loop, but only the test can be specified within the brackets. Both initialisation and increment must be done outside the brackets. The code below is equivalent to our first for loop example. + +```c +int i = 0; +while (i < 10) { + printf("%d\n", i); + i++; +} +``` + +Finally, the do while loop is similar to the other two loops, but with one important difference. + +> Question: Can you figure out what it is? + +```c +int i = 0; +do { + printf("%d\n", i); + i++; +} while (i < 10); +``` + +Let’s put this into practice by writing some code. + +==action:Using argc and argv, write some code that loops through the arguments passed by the user at runtime and prints them to the screen.== +> Aim for the output below: + +![][image-17] + +## Functions {#functions} + +So far, we have been writing all our code inside the main function. However, we have called the printf() function to output text to the terminal, and earlier we called the sizeof() function to calculate the size of an array. When the main code calls a function, it passes the required values to it before delegating execution to the function. While the function is executing, the main function waits. Once the function returns, the main code continues from where it had stopped. We will take a much more in-depth look at what happens behind the scenes once we move onto assembly. For now, let’s get some practice writing functions. + +==action: Create a file called simple-function.c and enter the following code:== + +```c +#include + +float average(float a, float b); + +int main (int argc, char *argv[]) { + float x = 7.5f; + float y = 10.5f; + float result = average(x, y); + printf("The average is: %g\n", result); +} + +float average(float a, float b) { + return (a + b)/2; +} +``` + +==action: Compile and run your code.== + +Note how the function signature is declared before the main method. + +> Question: What happens if you remove that line? Why? Could you rearrange the code so you don't need to declare the function signature? + +It is your turn now. + +> Action: Modify the function above to calculate the average of three floating point numbers. + +> Action: Write a new function to calculate the VAT (20%) of a given price. + +## Pointers {#pointers} + +Pointers are perhaps the most dreaded feature of the C language, but they are widely used and one of the most useful concepts for malware analysis. Malware analysts rarely have the luxury of being able to access the source code, so it is important to develop a solid understanding of how programs are loaded into memory and executed by the CPU, down to which values are stored in which memory addresses and how and when these are accessed by malicious code. Of course, it all begins with a good foundation in C, and you will find that pointers are particularly helpful, so let’s get started. + +A good way to think of how pointers are represented in your computer’s memory is to imagine that each byte in memory is a bucket which can be empty or can contain data. Each bucket also has an address, as illustrated in the figure below. + +![][image-18] + +When we store data in memory, we simply put it in these buckets. The number of buckets we use depends on the size of the data, so a char, for example, would take up 1 bucket, but an int would take up 4 buckets since it occupies 4 bytes of memory. + +Let’s store the character ‘A’ in a bucket. + +![][image-19] + +We know that the bucket’s address is 0x0c. What if we wanted to store this information somewhere? Well, first of all, we need to know the size of the address data type so we know how many buckets to allocate to it. As it happens, in 32bit systems, an address or pointer occupies 4 bytes in memory. Perfect, so let’s reserve 4 buckets to store our address. + +![][image-20] + +Now buckets 0x0e to 0x11 contain data of type “pointer”. What exactly is this data though? It is simply the address of another bucket storing 8 bits or 1 byte of data (in this case, our character 'A'). It is worth taking a slight diversion here to look at the concept of endianness. Let’s think of the address 0x0c as 0x0000000c (they both represent the number 12 in decimal). As you can see in the illustration above, the least significant byte of the address, 0c, is stored in the lowest address in memory. The highest address in the picture (the last bucket), stores the most significant byte of the address, in this case, 0\. This is called little-endian ordering. Some architectures use the opposite ordering, big-endian, when storing bytes in memory. + +Watch the first 3 min of this video on endianness: + +[Endianness Explained With an Egg \- Computerphile](https://www.youtube.com/watch?v=NcaiHcBvDR4) + +### Pointers in practice {#pointers-in-practice} + +Let’s go back to our pointers to see what they look like in code. + +```c +char myChar = 'A'; +``` + +> Note: Nothing new here, right? I simply declared a variable called myChar and put the character 'A' in there. + +```c +char *myCharPointer; +``` + +> Note: Ok, so what is going on here? This is where C syntax differs from other high-level languages you may be familiar with. Whenever you see a variable being declared with an asterisk (*) before its name, the variable is a pointer. So, in the example above, read: declare a variable called myCharPointer, **of type pointer** (to a char). + +Now, let's assign an address to our new variable: + +```c +myCharPointer = &myChar; +``` + +> Note: Whenever you see a value being assigned with the ampersand (&) prefix, it means "the address of" in C. So, in the example above, read: assign **the address** **of** myChar to the myCharPointer variable. + +Let’s put it all together and run some code. + +==action: Create a file called pointers.c and enter the following code:== + +```c +#include + +int main(int argc, char *argv[]) { + char myChar = 'A'; + char *myCharPointer; + myCharPointer = &myChar; + + printf("The value of myChar is: %c\n", myChar); + printf("The value of myCharPointer is: %#x\n", myCharPointer); + return 0; +} +``` + +==action: Compile and run your code.== + +Did you get the same output? + +![][image-21] + +==action:Modify the code to use an int instead of a char. Print the sizes of both variables.== +> Aim for the output below. + +![][image-22] + +*(don’t forget to compile your code as a 32-bit program by using the \-m32 option as shown above)* + +> Tip: If you get an error when trying to use the -m32 option, it could be because there may be a dependency missing in this week’s VM. Please use Week 1’s VM to run this exercise, and let us know ([via GitHub](https://github.com/cliffe/HacktivityLabSheets)). + +Here is one last bit of syntax to remember for now. Suppose I have a variable of type char pointer, as in the first example we looked at. + +```c +char myChar = 'A'; +char *myCharPointer = &myChar; +``` + +We know that the myCharPointer variable stores an address to a char. Now what if we wanted to follow the address and print the value of the char stored in there? We can use the dereferencing "*" operator: + +```c +#include + +int main(int argc, char *argv[]) { + char myChar = 'A'; + char *myCharPointer = &myChar; + char c = *myCharPointer; + + printf("The value stored in the address that is stored in myCharPointer is: %c\n", c); + return 0; +} +``` + +Here we create a new char variable called c and assign it the value stored in the address stored in myCharPointer, which evaluates to ‘A’. You can read it as: go to the address you have and give me **the value** stored there. + +==action: Modify the code you used to print integer pointers. Add a line showing how to access the value stored in the address that your pointer variable is pointing to.== + +To recap: + +| Code | Explanation | +| :---: | :---- | +| `int *myPointer;` | Declare a variable called myPointer of type pointer (to an int). | +| `myPointer = &myInt;` | Assign **the address** **of** myInt to myPointer. | +| `int x = *myPointer;` | **Follow** myPointer and assign **the value** at that address to x. | + +### Pointers and arrays {#pointers-and-arrays} + +This is where pointers get really interesting. Pointers are very similar to arrays and, a lot of the time, they can be used interchangeably. When you declare an array of 4 elements of type integer, you are saying: “give me a space in memory the size of 4 integers (remember each integer occupies 4 bytes, so we are asking for 16 bytes) and point to the first element in there”. + +```c +int myNumbers [4] = {1, 2, 3, 4}; +``` + +Your array variable points to the first element so the computer knows where in memory the array starts. It has a fixed type and size so the computer knows how much memory is occupied and where the array ends. + +Since an array variable simply points to the start of an array, you can assign it to a variable of type pointer. + +```c +int *myNumbersPointer = myNumbers; +``` + +> Question: What do you think the code below will print? + +```c +#include + +int main(int argc, char *argv[]) { + int myNumbers [4] = {1, 2, 3, 4}; + int *myNumbersPointer = myNumbers; + printf("The myNumbers array is: %p\n", myNumbers); + printf("The myNumbersPointer pointer is: %p\n", myNumbersPointer); + return 0; +} +``` + +==action: Create a file, add the code above, compile and run it to check if you were right.== + +> Action: Modify the code above to print the elements of the array using square brackets [ ] to access each element. + +> Question: Does the bracket notation work with both arrays and pointers? Try it out. + +Create a new file called arrays-and-pointers.c and enter the following code: + +==action: Create a file called arrays-and-pointers.c and enter the following code:== + +```c +#include + +int main(int argc, char *argv[]) { + int myNumbers [4] = {1, 2, 3, 4}; + int *myNumbersPointer = myNumbers; + + for (int i = 0; i < 4; i++) { + printf("%d ", myNumbers[i]); + } + + printf("\n"); + + for (int i = 0; i < 4; i++) { + printf("%d ", *(myNumbersPointer + i)); + } + + return 0; +} +``` + +==action: Compile and run the code.== + +A final note on pointers: you can have double pointers\! Take a look at the example below: + +```c +char *names [] = {"this", "is", "the", "end"}; +char **namesPointer = names; +``` + +> Action: Write two for loops like you did in the arrays-and-pointers.c program to print the contents of the array and pointer declared above. + +## Conclusion {#conclusion} + +At this point you have: + +* Written, compiled and executed C programs to familiarise yourself with basic C syntax +* Used arrays, conditionals, loops and functions in your programs +* Learned more advanced memory management features of the C language and practiced using pointers. + +Well done\! + +We have covered quite a lot this week. If any of the concepts are not clear, feel free to create your own coding samples to investigate them further and, of course, feel free to share them with us on the Discord channel. All the good work you have done in C will set the foundation for being able to understand assembly instructions in the weeks to come. + + +[image-1]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-1.png +[image-2]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-2.png +[image-3]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-3.png +[image-4]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-4.png +[image-5]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-5.png +[image-6]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-6.png +[image-7]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-7.png +[image-8]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-8.png +[image-9]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-9.png +[image-10]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-10.png +[image-11]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-11.png +[image-12]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-12.png +[image-13]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-13.png +[image-14]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-14.png +[image-15]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-15.png +[image-16]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-16.png +[image-17]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-17.png +[image-18]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-18.png +[image-19]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-19.png +[image-20]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-20.png +[image-21]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-21.png +[image-22]: {{ site.baseurl }}/assets/images/software_and_malware_analysis/2_intro_to_c/image-22.png diff --git a/_layouts/lab.html b/_layouts/lab.html index 70dd441..46cf3c1 100644 --- a/_layouts/lab.html +++ b/_layouts/lab.html @@ -402,6 +402,71 @@ document.addEventListener('DOMContentLoaded', function() { ); } }); + + // Convert YouTube links to embedded videos + const youtubeLinks = contentBody.querySelectorAll('a[href*="youtu.be"], a[href*="youtube.com/watch"]'); + youtubeLinks.forEach(link => { + const href = link.href; + let videoId = ''; + + // Extract video ID from different YouTube URL formats + if (href.includes('youtu.be/')) { + videoId = href.split('youtu.be/')[1].split('?')[0]; + } else if (href.includes('youtube.com/watch?v=')) { + videoId = href.split('v=')[1].split('&')[0]; + } + + if (videoId) { + // Create embedded iframe + const iframe = document.createElement('iframe'); + iframe.src = `https://www.youtube.com/embed/${videoId}`; + iframe.width = '560'; + iframe.height = '315'; + iframe.frameBorder = '0'; + iframe.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture'; + iframe.allowFullscreen = true; + iframe.style.cssText = 'max-width: 100%; height: auto; border-radius: 8px; margin: 1rem 0; transition: all 0.3s ease;'; + + // Create container div + const container = document.createElement('div'); + container.className = 'youtube-embed'; + container.style.cssText = 'text-align: center; margin: 1rem 0; cursor: pointer;'; + + // Add hover effects with delay + let hoverTimeout = null; + + container.addEventListener('mouseenter', function() { + // Clear any existing timeout + if (hoverTimeout) { + clearTimeout(hoverTimeout); + hoverTimeout = null; + } + + iframe.style.transform = 'scale(1.05)'; + iframe.style.height = '400px'; // Make it taller on hover + }); + + container.addEventListener('mouseleave', function() { + // Set a timeout to return to normal size after 30 seconds + hoverTimeout = setTimeout(function() { + iframe.style.transform = 'scale(1)'; + iframe.style.height = 'auto'; // Return to original height + hoverTimeout = null; + }, 30000); // 30 seconds delay + }); + + // Add the link text as a caption + const caption = document.createElement('p'); + caption.textContent = link.textContent; + caption.style.cssText = 'font-style: italic; color: var(--fg-color); opacity: 0.8; margin-top: 0.5rem;'; + + container.appendChild(iframe); + container.appendChild(caption); + + // Replace the link with the embedded video + link.parentNode.replaceChild(container, link); + } + }); } }); diff --git a/assets/css/hacktivity-theme.scss b/assets/css/hacktivity-theme.scss index b594b22..d64b97d 100644 --- a/assets/css/hacktivity-theme.scss +++ b/assets/css/hacktivity-theme.scss @@ -1412,3 +1412,14 @@ mark, .highlight-text{ text-decoration: none; } +// Add a small caption below images +img + em, +a:has(img) + em { + font-size: 0.8em; + font-style: italic; + display: block; + margin-top: 0.5rem; + margin-bottom: 0.5rem; + text-align: center; +} + diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-10.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-10.png new file mode 100644 index 0000000..7790876 Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-10.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-11.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-11.png new file mode 100644 index 0000000..8559647 Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-11.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-12.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-12.png new file mode 100644 index 0000000..cbbac43 Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-12.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-13.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-13.png new file mode 100644 index 0000000..80d7fe8 Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-13.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-14.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-14.png new file mode 100644 index 0000000..39f3a58 Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-14.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-15.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-15.png new file mode 100644 index 0000000..a6ea933 Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-15.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-16.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-16.png new file mode 100644 index 0000000..75c26bf Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-16.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-17.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-17.png new file mode 100644 index 0000000..aa34dfb Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-17.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-18.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-18.png new file mode 100644 index 0000000..24ec53c Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-18.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-19.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-19.png new file mode 100644 index 0000000..1d6815e Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-19.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-2.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-2.png new file mode 100644 index 0000000..6e48272 Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-2.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-20.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-20.png new file mode 100644 index 0000000..063d329 Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-20.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-21.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-21.png new file mode 100644 index 0000000..a6f7fc3 Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-21.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-22.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-22.png new file mode 100644 index 0000000..f92f735 Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-22.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-3.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-3.png new file mode 100644 index 0000000..275a490 Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-3.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-4.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-4.png new file mode 100644 index 0000000..080ff55 Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-4.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-5.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-5.png new file mode 100644 index 0000000..1cae2c1 Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-5.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-6.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-6.png new file mode 100644 index 0000000..5b5fe2e Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-6.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-7.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-7.png new file mode 100644 index 0000000..a9ff2e7 Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-7.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-8.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-8.png new file mode 100644 index 0000000..1f2956f Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-8.png differ diff --git a/assets/images/software_and_malware_analysis/2_intro_to_c/image-9.png b/assets/images/software_and_malware_analysis/2_intro_to_c/image-9.png new file mode 100644 index 0000000..238a350 Binary files /dev/null and b/assets/images/software_and_malware_analysis/2_intro_to_c/image-9.png differ