0

I have this c++ code to read the source of a webpage.

#include "stdafx.h"
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <fstream>
#pragma comment(lib,"ws2_32.lib")

using namespace std;

int main(){
    WSADATA wsaData;

    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        cout << "WSAStartup failed.\n";
        system("pause");
        return 1;
    }

    SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    struct hostent *host;
    host = gethostbyname("www.last.fm");

    SOCKADDR_IN SockAddr;
    SockAddr.sin_port = htons(80);
    SockAddr.sin_family = AF_INET;
    SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);

    cout << "Connecting...\n";
    if (connect(Socket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr)) != 0){
        cout << "Could not connect";
        system("pause");
        return 1;
    }
    cout << "Connected.\n";

    send(Socket, "GET /music/Taylor+swift/+albums?order=reach&page=1 HTTP/1.1\r\nHost: www.last.fm\r\nConnection: close\r\n\r\n", strlen("GET /music/taylor+swift/+albums?order=reach&page=1 HTTP/1.1\r\nHost: www.cplusplus.com\r\nConnection: close\r\n\r\n"), 0);
    char buffer[10000];

    int nDataLength;
    while ((nDataLength = recv(Socket, buffer, 10000, 0)) > 0){
        int i = 0;
        while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {
             cout << buffer[i];         
            i += 1;
        }
    }

    closesocket(Socket);
    WSACleanup();


    system("pause");
    return 0;
}

I tried to convert this to fasm assembly but it did not work. could someone help me convert it to assembly? thanks (note I have never worked with sockets in asm before so I am not sure if this code is close or not, I think it connects, but it gives a blank messagebox instead of the webpage sourcecode)

format PE GUI 4.0
entry start

include '\Fasm\INCLUDE\win32ax.inc'

section '.data' data readable writeable
  IPPROTO_TCP  = 6


wsadata WSADATA
 _caption db 'Client application',0
 _igang db 'The client has started very well.',13,10,'It is now going to connect to your own computer',0
 _hostname db 'Wrong hostname',0

  hostname db 'www.lastfm.com',0
  hSock dd ?
  saddr sockaddr_in
  sizesaddr = $-saddr


  buffer rb 0x3000

  sender db 'GET /music/Taylor+swift/+albums?order=reach&page=1 HTTP/1.1\r\nHost: www.last.fm\r\nConnection: close\r\n\r\n',13,10
         rb 0x100

section '.code' code readable executable
start:

       invoke WSAStartup,0101h,wsadata  ; initialiserer winsock-bibliotek

       invoke  ws_gethostbyname,hostname
       or     eax,eax
       jz     bad_hostname
              virtual at eax
               .host hostent
              end virtual
       mov    eax,[.host.h_addr_list]
       mov    eax,[eax]
       mov    eax,[eax]
       mov     [saddr.sin_addr],eax
       invoke MessageBox,0,_igang,_caption,0
       mov    al,00
       mov    ah,80          ; port 80
       mov     [saddr.sin_port],ax
       mov     [saddr.sin_family],AF_INET
       invoke  ws_socket, AF_INET, SOCK_STREAM, IPPROTO_TCP
       mov     [hSock], eax
       xchg    eax, esi
       invoke  ws_connect, esi, saddr, sizesaddr
       .if eax = 0
       invoke MessageBox,0, "connected", _caption,0
       .endif
       .if eax <> 0
       invoke MessageBox,0, "not connected", _caption,0
       .endif
       mov     ebx, buffer
       invoke  ws_send,esi,sender,109,0
       invoke  ws_recv, esi, ebx, 1000, 0
       invoke MessageBox,0, buffer, _caption,0
       .connectSucceeded:
       invoke ws_closesocket,esi
       invoke WSACleanup
       jmp stopp

bad_hostname:
        invoke MessageBox,0,_hostname,_caption,0
        jmp stopp

stopp:
        invoke ExitProcess,0



section '.idata' import data readable writeable

  library kernel,'KERNEL32.DLL',\
          winsock,'WSOCK32.DLL',\
          user,'USER32.DLL'

  import kernel,\
         ExitProcess,'ExitProcess'

  import winsock,\
        WSAStartup,'WSAStartup',\
        ws_socket,'socket',\
        ws_connect,'connect',\
        ws_gethostbyname,'gethostbyname',\
        ws_send,'send',\
        ws_recv,'recv',\
        ws_closesocket,'closesocket',\
        WSACleanup,'WSACleanup'

  import user,\
        MessageBox,'MessageBoxA'
Darrin Woolit
  • 69
  • 1
  • 7
  • 2
    _"could someone help me convert it to assembly?"_ is not a particularly good question to ask at StackOverflow. Can you point to a specific part of the code that you're having trouble with? (include an explanation of what you expect that piece of code to do and what it's actually doing) – Michael May 24 '14 at 19:51
  • it seems like it is connecting to lastfm on port 80, but I don't think it is sending the correct GET message. – Darrin Woolit May 24 '14 at 20:00
  • I don't have much experience with this, but I can tell you that the format of the GET message is very picky. I wonder if "/n/r" is being escaped correctly. I'd try replacing them with an explicit "13, 10" unless you're sure that's what you're getting. – Frank Kotler May 24 '14 at 20:11

2 Answers2

2

This my inet function, maybe will help you.

push cookie
push post
push url
push buffer 
call connectHTTP

The result is placed in the buffer. Function is not optimized but works stable.

; ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~
;
;  inet.asm
;
;  HFT -> inet functions
;
;  Copyright (C) 2013 Ilya M. Chirkunov (cheebeez@yandex.ru)
;
; - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ - ~ -

format ELF

include 'cdecl.inc'

public connectHTTP

extrn  gethostbyname
extrn  socket
extrn  htons
extrn  connect
extrn  send
extrn  recv
extrn  close
extrn  strcpy2
extrn  strcat2
extrn  strpos
extrn  strlen2
extrn  hex2decascii
extrn  push_ad
extrn  pop_ad

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;                                       С Е К Ц И Я  К О Д А
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

section '.text' executable

; ------------------------------------- HTTP запрос

proc connectHTTP

        call    push_ad

        pop     eax                                           ; сохраняем адрес возврата
        pop     edi esi ecx edx                               ; edi - buffer, esi - url, ecx - post, edx - cookie
        push    eax                                           ; восстанавливаем адрес возврата

;       (составляем запрос)
        sub     esp,10000
        mov     ebx,esp                                       ; в ebx будем собирать запрос

        cmp     dword[esi],"http"
        jne     _not_http
        add     esi,7                                         ; убираем "http://"
    _not_http:

        push    szPOST
        push    ebx
        call    strcpy2                                       ; "POST " 
        cmp     ecx,0
        jnz     _is_post

        push    szGET
        push    ebx
        call    strcpy2                                       ; "GET " 

    _is_post:
        push    szSlash
        push    ebx
        call    strcat2                                       ; "GET /" 

        push    esi
        push    edi
        call    strcpy2                                       ; копируем url в буффер

        push    szSlash
        push    edi
        call    strpos                                        ; ищем URI
        cmp     eax,-1
        je      _only_host
        mov     byte[edi+eax],0                               ; в edi - host
        add     esi,eax                                       ; в esi - uri
        inc     esi

        push    esi
        push    ebx
        call    strcat2                                       ; "GET /full_uri HTTP/1.0"

_only_host:
        push    szHTTP10
        push    ebx
        call    strcat2                                       ; "GET / HTTP/1.0" 
        push    szDA
        push    ebx
        call    strcat2                                       ; "GET / HTTP/1.0",0xD,0xA
        push    szHost
        push    ebx
        call    strcat2                                       ; "GET / HTTP/1.0",0xD,0xA,"Host: "
        push    edi
        push    ebx
        call    strcat2                                       ; "GET / HTTP/1.0",0xD,0xA,"Host: sphost.org"
        push    szDA
        push    ebx
        call    strcat2                                       ; "GET / HTTP/1.0",0xD,0xA,"Host: sphost.org",0xD,0xA

        cmp     ecx,0
        jz      _finish_query_string

        push    szContType
        push    ebx
        call    strcat2                                       ; "POST / HTTP/1.0",0xD,0xA,"Host: sphost.org",0xD,0xA,"Content-Type: application/x-www-form-urlencoded"
        push    szDA
        push    ebx
        call    strcat2                                       ; "POST / HTTP/1.0",0xD,0xA,"Host: sphost.org",0xD,0xA,"Content-Type: application/x-www-form-urlencoded",0xD,0xA
        push    szLength
        push    ebx
        call    strcat2                                       ; "POST / HTTP/1.0",0xD,0xA,"Host: sphost.org",0xD,0xA,"Content-Length: "

        push    ecx
        call    strlen2
        push    eax
        push    szSize
        call    hex2decascii

        push    szSize
        push    ebx
        call    strcat2                                       ; "POST / HTTP/1.0",0xD,0xA,"Host: sphost.org",0xD,0xA,"Content-Length: 64"
        push    szDA
        push    ebx
        call    strcat2                                       ; "POST / HTTP/1.0",0xD,0xA,"Host: sphost.org",0xD,0xA,"Content-Length: 64",0xD,0xA
        push    szDA
        push    ebx
        call    strcat2                                       ; "POST / HTTP/1.0",0xD,0xA,"Host: sphost.org",0xD,0xA,"Content-Length: 64",0xD,0xA,0xD,0xA
        push    ecx
        push    ebx
        call    strcat2                                       ; "POST / HTTP/1.0",0xD,0xA,"Host: sphost.org",0xD,0xA,"Content-Length: 64",0xD,0xA,0xD,0xA,"post"
        push    szDA
        push    ebx
        call    strcat2                                       ; "POST / HTTP/1.0",0xD,0xA,"Host: sphost.org",0xD,0xA,"Content-Length: 64",0xD,0xA,0xD,0xA,"post",0xD,0xA

_finish_query_string:
        push    szDA
        push    ebx
        call    strcat2                                       ; "GET / HTTP/1.0",0xD,0xA,"Host: sphost.org",0xD,0xA,0xD,0xA

;       (отправляем запрос)
        ccall   gethostbyname, edi
        ;cmp     eax,0
        ;jz      _ret_conHTTP
        mov     eax,[eax+16]
        mov     eax,[eax]
        mov     eax,[eax]
        mov     dword[sin_addr],eax

        ccall   socket, 2, 1, 6                               ; AF_INET, SOCK_STREAM, IPPROTO_TCP
        ;cmp     eax, -1
        ;je      _ret_conHTTP
        mov     dword[sockfd],eax

        ccall   htons, 80
        mov     word[sin_port],ax
        mov     word[sin_family],2

        ccall   connect, dword[sockfd], sin_family, 16
        ;cmp     eax,0
        ;jnz     _ret_conHTTP

        push    ebx
        call    strlen2

        ccall   send, dword[sockfd], ebx, eax, 0
        add     esp,10000

;       (получаем ответ)
    _getURL_recv:
        ccall   recv, dword[sockfd], edi, 1024, 0
        add     edi,eax
        cmp     eax,0
        jnz     _getURL_recv
        mov     byte[edi],0

        ccall   close,dword[sockfd]

_ret_conHTTP:
        call    pop_ad
        ret

endp

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;                                       С Е К Ц И Я  Д А Н Н Ы Х
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

section '.data' writeable

  szGET             db "GET ", 0
  szPOST            db "POST ", 0
  szSlash           db "/",0
  szHTTP10          db " HTTP/1.0",0
  szDA              db 0xD,0xA,0
  szHost            db "Host: ", 0
  szContType        db "Content-Type: application/x-www-form-urlencoded",0
  szLength          db "Content-Length: ", 0
  szSize            db 12 dup (0)
  sockfd            dd 0

; sockaddr_in       db 16 dup (0)
  sin_family        db 2 dup (0)
  sin_port          db 2 dup (0)
  sin_addr          db 4 dup (0)
  sin_zero          db 8 dup (0)
cheebeez
  • 113
  • 6
1

I highly recommend that you do not bother with sockets and just use functions from WinInet since you're on Windows. This WinAPI is quite easy to use in fASM.