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

CMP или TEST

Wolfomeo

RAID-массив
Пользователь
Регистрация
15.05.2011
Сообщения
81
Реакции
4
Имеем такой код на fasm:
Код:
format PE GUI on 'nul'
entry start_program
section '.TEST' code import writeable readable executable

include 'win32ax.inc'

; макрос XOR'а строк
macro crypt start, length, key
{
  local x, y, key_size, key_pos
  virtual at 0
    db key
    key_size = $
  end virtual
  key_pos = 0
  repeat length
    load x from start + % - 1
    virtual at 0
      db key
      load y from key_pos
    end virtual
    x = x xor y
    store x at start + % - 1
    key_pos = key_pos + 1
    if key_pos >= key_size
      key_pos = 0
    end if
  end repeat
}

; импорт
library kernel_lib, 'kernel32.dll',\
	user_lib, 'user32.dll'

import	kernel_lib,\
	exit_func, 'ExitProcess'

import	user_lib,\
	mess_func, 'MessageBoxA'

; точка входа в программу
start_program:

; декрипт строк
  call decrypt_code
; выполнение кода
  call start_code

; код для декрипта строк
decrypt_code:
  mov edi, xoring_start
  mov ecx, xoring_end - xoring_start
@@:
  xor byte[edi],8
  inc edi
  dec ecx
  test ecx,ecx
  jnz @b; @b - прерывание цикла
  ret

; строки которые мы ксорим
xoring_start:
  text db 'Текст', NULL
  zagol db 'Заголовок', NULL
  ret
xoring_end:

start_code:
; показываем сообщение
  invoke mess_func, NULL, text, zagol, MB_OK + MB_ICONEXCLAMATION
; выходим
  invoke exit_func, NULL


; выполняем макрос с ключом XOR'а 8
crypt xoring_start, xoring_end - xoring_start, 8

Метка "код для декрипта строк", имеет команду:
Код:
test ecx,ecx
4cbe62df2155.png


Насколько мне известно, также существует аналог:
Код:
cmp ecx,ecx
fd0394073f99.png


Собственно разницу видно на скриншотах. Почему так?


В сети нашел следующее:
Команды вида test reg,reg используется для сравнения значения регистра с нулем, т.е. после этой операции либо устанавливается либо сбрасывается флаг нуля (а также флаг знака и флаг четности). Почему не cmp reg,0? Потому что в скомпилированном виде test reg,reg на целый байт короче, ну и по скорости наверное разница есть:)

test эквивалентен битовому and, за исключением того, что не модифицируются операнды, а только флаги. Обычно это нужно, чтобы узнать, установлены ли определенные биты в регистре.

P.S. а cmp эквивалентен обыкновенному вычитанию, но аналогично не модифицирует операнды, а модифицирует флаги.
Наверное из-за того что короче, да..?

В общем охота услышать мнение знатоков (=
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Насколько я знаю, cmp - это вычитание, т.е. вычитается одно значение с другого, и устанавливаются флаги. А test - это побитовая операция, как and, только результаты никуда не записываются.

Т.е. смотри. У тебя в цикле идет проверка регистра ecx на 0, если 0 - выход из цикла. При сравнении через test все идет нормально, потому что тестируются все биты регистра, и пока хоть один установлен, цикл продолжается. Cmp же вычитает одно и другого, и сразу устанавливает флаг нуля. Поэтому цикл прервется после первой же итерации.

В общем говоря, test ecx,ecx != cmp ecx,ecx, а равно cmp ecx,0.
 
Спасибо за ответы, оказалось всё проще простого (=

Еще вопрос на засыпку, абы не создавать новую тему:
располагает ли язык C подобными макросредствами, для решения таких задач ("на лету" ксорить строки, аналогично вышеуказанному примеру)?
 
фасм в этом плане гибче. в студии к примеру нет подобных возможностей, зато энтузиацсты замутили компайл-тайм хаки для формата C++11, так что и в си++ можно шифровать и хэшировать строки, гуглить Malware related compile-time hacks with C++11
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Wolfomeo
Да поксорить строки в Си можно конечно же, но вот с всем другим - хз. Тот же ror/rol вроде как реализуется с большим гемором.
На С не пишу, так что мб ошибаюсь.
 
я не секу в макросах и шаблонах настолько что бы сделать подобное, но как сказали выше есть реализация на шаблонах, а очень давно видел что то подобное на макросах, так что да это возможно, но как это сделать хз.

вообще не стоит этим заниматься имхо, обычно бинарь покрывают криптором и наличие в нем каких то строк само по себе уже не важно, если же это делается для доп протекции и усложнения анализа, то опять же мимо, т.к. посидев чуток и набросав скрип для иды можно будет все строки дешифровать и анализировать дальше себе спокойно.
 
располагает ли язык C подобными макросредствами, для решения таких задач ("на лету" ксорить строки, аналогично вышеуказанному примеру)?
Разумеется, почему же нет? Там ещё и асм-вставки делать можно ;)
 
располагает ли язык C подобными макросредствами, для решения таких задач ("на лету" ксорить строки, аналогично вышеуказанному примеру)?
Код:
int result=0,a=0x3138342e,b=0x35363738;
result = a ^ b;

Код:
void main (int argc, char *argv[]) {
FILE *fl, *fo;
char *cp;
int c;
if ((cp = argv[l]) && *cp!= '\0') {
if ((fi = fopen(argvl[2], "rb")) != NULL) {
if ((fo = fopen(argv[3], "wb")) != NULL) {
while ((c = getc(fi)) != EOF) {
if (!*cp) cp = argv[1];
c^= *(cp++);
putc(c,fo); }
fclose(fo); }
fclose(fi);
}
}
 
shore
всё это хорошо, но шла речь о ксоре строк, на стадии препроцессинга, подобно примеру в первом посте.
Это не критично, можно организовать дело и в несколько шагов (к примеру написать простенькое приложение, которое будет искать эти самые строки, и шифровать их, а уж только потом, производить компиляцию). Просто выходит, что в фасм'е более развиты макросредства, и запилены под такие фокусы идеальным образом.
 
Wolfomeo туплю

а если так
Код:
#define s(a) a^0xc
#define o(p, q) s(p), q
char password[]={o('x',o('o',o('r',o('_',o('!',o('!',o('!',s('!'))))))))};

Код:
#include <string.h>
#include <unistd.h>

#define encodepass(var, pass)\
char var[sizeof(pass)-1];\
{\
  char _tmp[sizeof(pass)-1] = (pass);\
  char *_a= _tmp;\
  do\
  {\
    *_a ^= *(_a+1);\
    _a++;\
  } while( _a < &(_tmp[sizeof(pass)-1]) - 1 );\
  memcpy(var, _tmp, sizeof(pass)-1);\
}

#define decodepass(enc, dec)\
memcpy(dec, enc, sizeof(dec));\
{\
  char *_a= dec+sizeof(dec)-2;\
  do\
  {\
    *_a ^= *(_a+1);\
    _a--;\
  }while( _a >= dec);\
}

int main(void)
{
  encodepass(a, "asdasd"); // Создает переменную char a[длина_пароля] и пишет в нее зашифрованный пароль
  char b[sizeof(a)];
  decodepass(a, b); // Пишет в b расшифрованный пароль

  write(1, b, sizeof(b));
  return 0;
}

Еще в бусте что-то есть
http://www.boost.org/doc/libs/1_39_0/boost...logical/xor.hpp
 


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