// File: akw0088[P]openssl/download.cpp
// Function: file_download(char*, unsigned short, char*, int, unsigned int*, char*)
int file_download(char *ip_str, unsigned short int port, char *response, int size, unsigned int *download_size, char *file_name)
{
	struct sockaddr_in	servaddr;
	SOCKET sock;
	int ret;

	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	memset(&servaddr, 0, sizeof(struct sockaddr_in));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = inet_addr(ip_str);
	servaddr.sin_port = htons(port);

	// 3 way handshake
	printf("Attempting to connect to %s\n", ip_str);
	ret = connect(sock, (struct sockaddr *)&servaddr, sizeof(struct sockaddr_in));
	if (ret == SOCKET_ERROR)
	{
#ifdef _WIN32
		ret = WSAGetLastError();

		switch (ret)
		{
		case WSAETIMEDOUT:
			printf("Fatal Error: Connection timed out.\n");
			break;
		case WSAECONNREFUSED:
			printf("Fatal Error: Connection refused\n");
			break;
		case WSAEHOSTUNREACH:
			printf("Fatal Error: Router sent ICMP packet (destination unreachable)\n");
			break;
		default:
			printf("Fatal Error: %d\n", ret);
			break;
		}
#else
		ret = errno;

	        switch(ret)
	        {
		case ENETUNREACH:
			printf("Fatal Error: The network is unreachable from this host at this time.\n(Bad IP address)\n");
			break;
	        case ETIMEDOUT:
	                printf("Fatal Error: Connecting timed out.\n");
	                break;
	        case ECONNREFUSED:
	                printf("Fatal Error: Connection refused\n");
	                break;
	        case EHOSTUNREACH:
	                printf("Fatal Error: router sent ICMP packet (destination unreachable)\n");
	                break;
	        default:
	                printf("Fatal Error: %d\n", ret);
	                break;
	        }
#endif
		return -1;
	}
	printf("TCP handshake completed\n");

	memset(response, 0, size);

	int expected_size = 0;
	recv(sock, (char *)&expected_size, 4, 0);
	recv(sock, (char *)file_name, 128, 0);

	while (*download_size < expected_size)
	{
		*download_size += recv(sock, &response[*download_size], expected_size - *download_size, 0);
	}
	closesocket(sock);
	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movw %si, %ax
movq %rdi, -0x10(%rbp)
movw %ax, -0x12(%rbp)
movq %rdx, -0x20(%rbp)
movl %ecx, -0x24(%rbp)
movq %r8, -0x30(%rbp)
movq %r9, -0x38(%rbp)
movl $0x2, %edi
movl $0x1, %esi
movl $0x6, %edx
callq 0x10a0
movl %eax, -0x4c(%rbp)
leaq -0x48(%rbp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x1110
movw $0x2, -0x48(%rbp)
movq -0x10(%rbp), %rdi
callq 0x1180
movl %eax, -0x44(%rbp)
movzwl -0x12(%rbp), %edi
callq 0x1070
movw %ax, -0x46(%rbp)
movq -0x10(%rbp), %rsi
leaq 0xb38(%rip), %rdi       # 0x207b
movb $0x0, %al
callq 0x1060
movl -0x4c(%rbp), %edi
leaq -0x48(%rbp), %rsi
movl $0x10, %edx
callq 0x1140
movl %eax, -0x50(%rbp)
cmpl $-0x1, -0x50(%rbp)
jne 0x15f4
callq 0x1050
movl (%rax), %eax
movl %eax, -0x50(%rbp)
movl -0x50(%rbp), %eax
addl $-0x65, %eax
movl %eax, %ecx
movq %rcx, -0x60(%rbp)
subl $0xc, %eax
ja 0x15d7
movq -0x60(%rbp), %rax
leaq 0xa76(%rip), %rcx       # 0x2004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0xafa(%rip), %rdi       # 0x2098
movb $0x0, %al
callq 0x1060
jmp 0x15e8
leaq 0xb41(%rip), %rdi       # 0x20ef
movb $0x0, %al
callq 0x1060
jmp 0x15e8
leaq 0xb55(%rip), %rdi       # 0x2113
movb $0x0, %al
callq 0x1060
jmp 0x15e8
leaq 0xb66(%rip), %rdi       # 0x2134
movb $0x0, %al
callq 0x1060
jmp 0x15e8
movl -0x50(%rbp), %esi
leaq 0xb93(%rip), %rdi       # 0x2174
movb $0x0, %al
callq 0x1060
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x168c
leaq 0xb8a(%rip), %rdi       # 0x2185
movb $0x0, %al
callq 0x1060
movq -0x20(%rbp), %rdi
movslq -0x24(%rbp), %rdx
xorl %esi, %esi
callq 0x1110
movl $0x0, -0x54(%rbp)
movl -0x4c(%rbp), %edi
leaq -0x54(%rbp), %rsi
movl $0x4, %edx
xorl %ecx, %ecx
callq 0x10c0
movl -0x4c(%rbp), %edi
movq -0x38(%rbp), %rsi
movl $0x80, %edx
xorl %ecx, %ecx
callq 0x10c0
movq -0x30(%rbp), %rax
movl (%rax), %eax
cmpl -0x54(%rbp), %eax
jae 0x167d
movl -0x4c(%rbp), %edi
movq -0x20(%rbp), %rsi
movq -0x30(%rbp), %rax
movl (%rax), %eax
addq %rax, %rsi
movl -0x54(%rbp), %eax
movq -0x30(%rbp), %rcx
subl (%rcx), %eax
movl %eax, %eax
movl %eax, %edx
xorl %ecx, %ecx
callq 0x10c0
movq %rax, %rdx
movq -0x30(%rbp), %rax
movl (%rax), %ecx
addq %rdx, %rcx
movl %ecx, (%rax)
jmp 0x163e
movl -0x4c(%rbp), %edi
callq 0x1220
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)