Q:

Hijacking function calls by rewriting the address used by the PLT jump

I need to solve a problem where I need to enter an address and value to store at that address to be able to hijack a function call. The function call that I believe I need to hijack is the sleep() function. 
0x4a7078b5 is the address of the sleep function that is being called. 0x4a707776 is the value of the print_good() function that I want to store in the address. These are the values that I believe I need to input to get the answer. However I'm not getting the correct answer when I type them in.
Here is the c code that I'm given:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>

char msg[] =
 "(From overthewire.org) When pointers are corrupted from format string\n"
 "vulnerabilities and heap overflows, an adversary can inject arbitrary\n"
 "input into critical parts of a process's memory.  One such area for\n"
 "corruption is the procedure link table: a table of function pointers\n"
 "that support dynamically linked library calls.  The table is filled in at\n"
 "load time to support run-time code relocation and is often left writeable.\n"
 "In this level, you are allowed one arbrtrary write to an arbitrary memory\n"
 "location between 0x0 and 0xff000000 to unlock the program.  We have added\n"
 "a call to sleep() that you may hijack. To do so, use objdump\" or \"gdb\"\n"
 "to find its PLT entry, the memory location to overwrite and the address of\n"
 "the function to execute instead.  We have included the source code for you\n"
 "to peruse. Note that the password will be read in using:\n"
 "  scanf(\"%lx \%lx\");\n\n";

void print_good() {
    printf("Good Job.\n");
    exit(0);
}
void segv_handler(int sig) {
    printf("Segmentation fault.  Try again.\n");
    exit(0);
}
void ill_handler(int sig) {
    printf("Illegal instruction hit.  Try again.\n");
    exit(0);
}
void print_msg() {
        printf("%s",msg);
}
int main()
{
    unsigned long int *ip;
    unsigned long int i;

    signal(SIGSEGV, segv_handler);
    signal(SIGILL, ill_handler);

    print_msg();
    printf("The password is a hexadecimal address and a hexadecimal value\n");
    printf("to place at that address.\n");
    printf("Enter the password: ");
    scanf("%lx %lx",(unsigned long int *) &ip,&i);
    if (ip > (unsigned long int *) 0xff000000) {
        printf("Address too high.  Try again.\n");
        exit(0);
    }
    *ip = i;
    printf("The address: %lx will now contain %lx\n",(unsigned long int) ip,i);
    sleep(1);
    printf("Try again.\n");
    exit(0);
}

I'm also given an executable of this c code. 
If you want to help me by doing it yourself here's the executable to do it:
http://www.mediafire.com/file/bnqri8my95zqwmz/Ch3_07_HijackPLT/file
Here's the c code:
http://www.mediafire.com/file/3lrty8b028te3d2/Ch3_07_HijackPLT.c/file
Use the executable to solve the problem.

A:

The scanf + *ip = i; lets you overwrite an unsigned long at any writeable address.  It looks like the code is assuming unsigned long is the same size as a pointer, and that that's the intended attack vector.  That's typical in Unix ABIs, but x86-64 Windows has 64-bit pointers and 32-bit long.
In most modern OSes, the program text (including the PLT itself1, in executables that have one2) won't be writeable, only stack, data, and BSS.  All of those are usually mapped without exec permission.  So there are typically no writeable + executable pages where you could modify code bytes directly through a wild pointer.
But the GOT (Global Offset Table), including the function pointers used by the PLT, stays mapped read+write so lazy dynamic linking can work without mprotect.  See The Sorry state of dynamic libraries on Linux for more about indirection through the PLT and GOT.
Your URL includes HijackPLT, so presumably that's the intended attack vector for the arbitrary overwrite of 4 or 8 bytes.  (And BTW, overwriting a GOT entry will work even with -fno-plt, unless the GOT is made read-only after early binding of shared libraries.)
Use a disassembler (or single-step with a debugger if the executable uses ASLR) to find out the address of the GOT entry for sleep, and give that as the address, and the address of your target function as the value.

If this is 32-bit x86 Linux, the ip < 0xff000000 check stops you from modifying stack memory (normally mapped at the top of user-space memory, or at the top of the low half of virtual address space).  On a 32-bit kernel, a 32-bit executable might have its stack at 0x7f... where you could modify it with this program.

Footnote 1:
IDK if historically the PLT itself was writeable and using a direct jump instead of indirect to an address loaded from the GOT.  That would slightly reduce the overhead of indirection through the PLT.  It would work for architectures like 32-bit x86 where a jmp rel32 can reach any target address, but not for x86-64 where shared libraries are typically loaded more than 2GiB away from a non-PIE executable.
But a PLT entry in a Linux i386 non-PIE 32-bit executable made by modern gcc7.3 on Arch Linux looks like this:
# from objdump -drwC -Mintel  on an executable from gcc -m32 -fno-pie -no-pie
08048350 <puts@plt>:
 8048350:       ff 25 0c a0 04 08       jmp    DWORD PTR ds:0x804a00c
 8048356:       68 00 00 00 00          push   0x0
 804835b:       e9 e0 ff ff ff          jmp    8048340 <.plt>

On the first call to puts@plt, the indirect jmp loads a jump target that takes it to the push instruction, and the jmp .plt takes it to code that calls the dynamic linker's symbol resolver (with 0 as the function arg for which symbol entry to resolve).
When it's done, it updates the GOT entry so future calls to this PLT entry will jmp directly to puts in libc.  Then it jumps there so this call runs the actual function before returning to the code that just wanted to call puts.
If the PLT itself was writeable, you could rewrite the 2nd jmp, the one that goes to the lazy dynamic linking resolver, if your attack happened before the first call to the target library function.  The GOT entry will never get updated so it will keep jumping to the next instruction.
Or, on x86-64 with a writeable PLT, you have 8 byte unsigned long so your write could include a complete 5-byte jmp rel32 instruction, replacing the indirect jmp with a direct jmp to the function you want.  But this is kinda silly because the PLT is part of the text segment and isn't mapped writeable unless you compile with weird options.  Just overwrite the GOT entry; that's easier anyway when you have total control over the address and data for an overwrite.

Footnote 2: Not all executables have a PLT at all: only in dynamically-linked executables, and usually only on Unix-like OSes.  Even on platforms that traditionally use a PLT for calls to functions in shared libraries,  -fno-plt will inline a memory-indirect call [sleep@got] instruction (x86 example), using PC-relative addressing for the GOT entry in PIC code, or if it's the most efficient way to address static data (e.g. x86-64).
Windows calls to functions in DLLs work similarly to gcc -fno-plt.

