Си изменение строки при инициализации

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by slesh, 28 May 2011.

  1. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Собственно говоря нужно инициализировать строку таким образом, чтобы каждый символ её был изменён.

    К примеру имеем макрос:
    #define ADD(_c_) _c_ + 3

    И его нужно применить к каждом символу строки при её инициализации.
    До этого использовал так
    char STR[] =
    {
    ADD('h'),
    ADD('e'),
    ADD('l'),
    ADD('l'),
    ADD('o')
    };

    Но это очень не удобно для большого кол-ва строк. Или если строки очень длинные, то запаришься всё так оформлять. Может кто-нибудь знает как это всё оформить в виде макроса?
     
  2. greki_hoy

    greki_hoy Member

    Joined:
    4 Mar 2010
    Messages:
    326
    Likes Received:
    57
    Reputations:
    41
    проверил на C/C++ VS2008
    Code:
    ///
    
    #include <boost/preprocessor.hpp>
    
    #define CT_INIT_WTF(...) , ## __VA_ARGS__
    
    #define CT_INIT_COUNT_PARMS2(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _, ...) _
    #define CT_INIT_REPEAT_PARAMS(...) (__VA_ARGS__)
    #define CT_INIT_COUNT_PARMS(...) \
       CT_INIT_COUNT_PARMS2 CT_INIT_REPEAT_PARAMS(CT_INIT_WTF(__VA_ARGS__) 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
    
    
    #define CT_INIT_MAKESEQ(n,...) BOOST_PP_TUPLE_TO_SEQ(n, (__VA_ARGS__))
    
    #define CT_INIT_MACRO(r,data,i,x) \
    	(((x)<=0xffu) ? ((x)&0xff)+(CT_INIT_MAGIC) : ((x)<=0xffffu) ? (((x)&0xff00)>>8)+(CT_INIT_MAGIC) : \
    	((x)<=0xffffffu) ? (((x)&0xff0000)>>16)+(CT_INIT_MAGIC) : (((x)&0xff000000)>>24)+(CT_INIT_MAGIC)) \
    	, \
    	(((x)<=0xffu) ? 0 : ((x)<=0xffffu) ? ((x)&0xff)+(CT_INIT_MAGIC) : \
    	((x)<=0xffffffu) ? (((x)&0xff00)>>8)+(CT_INIT_MAGIC) : (((x)&0xff0000)>>16)+(CT_INIT_MAGIC)) \
    	, \
    	(((x)<=0xffu) ? 0 : ((x)<=0xffffu) ? 0 : \
    	((x)<=0xffffffu) ? ((x)&0xff)+(CT_INIT_MAGIC) : (((x)&0xff00)>>8)+(CT_INIT_MAGIC)) \
    	, \
    	(((x)<=0xffu) ? 0 : ((x)<=0xffffu) ? 0 : \
    	((x)<=0xffffffu) ? 0 : ((x)&0xff)+(CT_INIT_MAGIC)) \
    	, \
    	BOOST_PP_IF(BOOST_PP_LESS(BOOST_PP_INC(i),data), BOOST_PP_EMPTY(), '\0')
    
    #define CT_INIT_IMPL(n,...) \
    	BOOST_PP_SEQ_FOR_EACH_I(CT_INIT_MACRO,n,CT_INIT_MAKESEQ(n,__VA_ARGS__))
    
    ///
    
    
    #define CT_INIT_MAGIC 3
    
    #define $(...) CT_INIT_IMPL(CT_INIT_COUNT_PARMS(__VA_ARGS__),__VA_ARGS__)
    
    
    
    int main()
    {
    	char buf[]={$('byte')};
    	char dup[]={$('shlw','api3','2.dl','l')};
    }
    
    Code:
    int main()
    {
    00411250 55               push        ebp  
    00411251 8B EC            mov         ebp,esp 
    00411253 83 EC 5C         sub         esp,5Ch 
    00411256 53               push        ebx  
    00411257 56               push        esi  
    00411258 57               push        edi  
    	char buf[]={$('byte')};
    00411259 C6 45 F8 65      mov         byte ptr [buf],65h 
    0041125D C6 45 F9 7C      mov         byte ptr [ebp-7],7Ch 
    00411261 C6 45 FA 77      mov         byte ptr [ebp-6],77h 
    00411265 C6 45 FB 68      mov         byte ptr [ebp-5],68h 
    00411269 C6 45 FC 00      mov         byte ptr [ebp-4],0 
    	char dup[]={$('shlw','api3','2.dl','l')};
    0041126D C6 45 E4 76      mov         byte ptr [dup],76h 
    00411271 C6 45 E5 6B      mov         byte ptr [ebp-1Bh],6Bh 
    00411275 C6 45 E6 6F      mov         byte ptr [ebp-1Ah],6Fh 
    00411279 C6 45 E7 7A      mov         byte ptr [ebp-19h],7Ah 
    0041127D C6 45 E8 64      mov         byte ptr [ebp-18h],64h 
    00411281 C6 45 E9 73      mov         byte ptr [ebp-17h],73h 
    00411285 C6 45 EA 6C      mov         byte ptr [ebp-16h],6Ch 
    00411289 C6 45 EB 36      mov         byte ptr [ebp-15h],36h 
    0041128D C6 45 EC 35      mov         byte ptr [ebp-14h],35h 
    00411291 C6 45 ED 31      mov         byte ptr [ebp-13h],31h 
    00411295 C6 45 EE 67      mov         byte ptr [ebp-12h],67h 
    00411299 C6 45 EF 6F      mov         byte ptr [ebp-11h],6Fh 
    0041129D C6 45 F0 6F      mov         byte ptr [ebp-10h],6Fh 
    004112A1 C6 45 F1 00      mov         byte ptr [ebp-0Fh],0 
    004112A5 C6 45 F2 00      mov         byte ptr [ebp-0Eh],0 
    004112A9 C6 45 F3 00      mov         byte ptr [ebp-0Dh],0 
    004112AD C6 45 F4 00      mov         byte ptr [ebp-0Ch],0 
    }
    004112B1 33 C0            xor         eax,eax 
    004112B3 5F               pop         edi  
    004112B4 5E               pop         esi  
    004112B5 5B               pop         ebx  
    004112B6 8B E5            mov         esp,ebp 
    004112B8 5D               pop         ebp  
    004112B9 C3               ret              
    
    все равно криво приходится делить на 4 буквы вместо 1
    так же неудобно
     
    2 people like this.
  3. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    не, слишком мутарно проще уже заюзать посимвольно
     
  4. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    Функция+Макрос.
    В принципе нет профта, хотя если сделать inline, то будет.

    UPD:
    greki_hoy, круто!
     
    #4 Jingo Bo, 29 May 2011
    Last edited: 29 May 2011
  5. GRRRL Power

    GRRRL Power Elder - Старейшина

    Joined:
    13 Jul 2010
    Messages:
    823
    Likes Received:
    185
    Reputations:
    84
    Функция не имеет возможности исполняться во время компиляции. А тут именно это и требуется, т.к. в программе после компиляции все строки уже зашифрованы должны быть.
    Боюсь, нормальным путем такое не реализуется даже с помощью шаблонов/C++0x.
     
  6. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,023
    Likes Received:
    1,311
    Reputations:
    327
    так вынеси их в отдельный хидер и колдуй над ним на Pre-Build Event какимнить скриптом

    зы ток они у тя все глобальные получатся, но в любом случае с билдэвентами можно как минимум это сделать
     
    #6 sn0w, 2 Jun 2011
    Last edited: 2 Jun 2011
  7. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    2 sn0w ну этого была уже подобная реализация, которая запускала спец прогу которая генерила файл. НО это не удобно т.к. не даёт возможности оперативно менять значения. А скрипты (перл и php ) както не подходят
     
  8. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,023
    Likes Received:
    1,311
    Reputations:
    327
    почему же не подходят? очень даже подходят, вот накидал прожект вместе с пхпешным энкодером (пришлось бинарники пхп добавить, поэтому 2метра), все на автомате, жуст пресс F7 ))

    ап добавил развернуто а то там дальше страсти начались
    (release конфиг)

    http://www.sendspace.com/file/thmq1i

    Code:
    //
    // gstrings.h
    //
    char g_name_str[] = "AAAAAAAAAAAAAAAA";
    char *g_somestr_2 = "Wow it works, its \"awesome\"";
    
    char *g_somestr_3 =			  "And there we shift the data";
    
    Code:
    //
    // stringtest.cpp
    //
    #include <stdio.h>
    #include <conio.h>
    
    #include "gstrings.enc" // edit gstrings.h instead of this header
    
    int main(int argc, char* argv[])
    {
    	printf("Encoded string: %s\n", g_name_str);
    	printf("Encoded string: %s\n", g_somestr_2);
    	printf("Encoded string: %s\n", g_somestr_3);
    	return getch();
    }
    

    Code:
    //
    // encode.php
    //
    <?php
    
    echo "ENCODE: executing encryption script...\r\n";
    
    unlink("..\stringtest\gstrings.enc");
    $lines = file("..\stringtest\gstrings.h");
    $encheader = fopen("..\stringtest\gstrings.enc", 'wb') ;
    
    foreach ($lines as $line_num => $line) {
    
    	$pos = strpos($line, '"');
    	fwrite($encheader, $line, $pos +1 );
    	
    	for($i = $pos + 1; $i < strlen($line); $i++)
    	{
    		if($line[$i]==="\"")
    		{
    			if($line[$i-1]!=="\\")
    			{
    				fwrite($encheader, "\";\r\n", 4);
    				break;
    			}
    		}
    		fwrite($encheader, chr(ord($line[$i]) + 1), 1); // ALGORITHM: INCREASE BYTE VALUE BY 1
    	}	
    }
    
    echo "ENCODE: done\r\n";
    ?>
    

    Code:
    1>------ Build started: Project: stringtest, Configuration: Release Win32 ------
    1>Build started 03.06.2011 17:58:37.
    1>InitializeBuildStatus:
    1>  Creating "Release\stringtest.unsuccessfulbuild" because "AlwaysCreate" was specified.
    1>PreBuildEvent:
    1>  ENCODE: executing encryption script...
    1>  ENCODE: done
    1>ClCompile:
    1>  stringtest.cpp
    1>Link:
    1>  Generating code
    1>  Finished generating code
    1>  stringtest.vcxproj -> D:\_coding\codes3\php_encode_strings\Release\stringtest.exe
    1>FinalizeBuildStatus:
    1>  Deleting file "Release\stringtest.unsuccessfulbuild".
    1>  Touching "Release\stringtest.lastbuildstate".
    1>
    1>Build succeeded.
    1>
    1>Time Elapsed 00:00:00.52
    ========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
    output:
    Code:
    Encoded string: BBBBBBBBBBBBBBBB
    Encoded string: Xpx!ju!xpslt-!jut!]#bxftpnf]#
    Encoded string: Boe!uifsf!xf!tijgu!uif!ebub
    
     
    #8 sn0w, 2 Jun 2011
    Last edited: 4 Jun 2011
    1 person likes this.
  9. R0nin

    R0nin Member

    Joined:
    11 Jul 2010
    Messages:
    261
    Likes Received:
    24
    Reputations:
    8
    Code:
    #include <cstdio>
    
    
    #define off 3
    
    #define h ('h'+off)
    #define e ('e'+off)
    #define l  ('l'+off)
    #define o ('o'+off)
    
    
    int main( void ) {
    
    	char arr_init[] = { h, e, l, l, o, 0 };
    	
    	printf( "str: %s\n", arr_init );
    
    }
    Для каждой буквы одно макро, и все это в заголовочный файл, вот и секрет твоего счастья :D
     
  10. Irdis

    Irdis Elder - Старейшина

    Joined:
    6 Feb 2006
    Messages:
    248
    Likes Received:
    52
    Reputations:
    3
    не лучшее решение, так как кто-то захочет использовать переменные i или j.
    и что делать с пробелами?
     
    #10 Irdis, 3 Jun 2011
    Last edited: 3 Jun 2011
  11. R0nin

    R0nin Member

    Joined:
    11 Jul 2010
    Messages:
    261
    Likes Received:
    24
    Reputations:
    8
    Ну это понятно.
    Место i, j на крайняк можно написать index, idx, idx_j/i и т.д.
    И не обязательно header файл с макросами загружать в каждый *c файл.

    С пробелами? ' '+off;
     
  12. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    имеется в виду имя переменной)
     
  13. R0nin

    R0nin Member

    Joined:
    11 Jul 2010
    Messages:
    261
    Likes Received:
    24
    Reputations:
    8
    i, j часто используются в for() как переменные-индексы, поэтому и говорю, что можно отказаться от этих названий.
     
    #13 R0nin, 3 Jun 2011
    Last edited: 3 Jun 2011
  14. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,023
    Likes Received:
    1,311
    Reputations:
    327
    можно кстати все строки в отдельный data_seg затолкать и после сборки проезжать по нему ксором или чем удобно. а при запуске проги, заведомо процедура с обратным ключом
     
  15. R0nin

    R0nin Member

    Joined:
    11 Jul 2010
    Messages:
    261
    Likes Received:
    24
    Reputations:
    8
    slesh, так что там, придумал что нибудь?
     
  16. greki_hoy

    greki_hoy Member

    Joined:
    4 Mar 2010
    Messages:
    326
    Likes Received:
    57
    Reputations:
    41
    можно так еще только чтоб компилятор выкинул ссылки на строки (и сами строки)
    надо включить оптимизацию или по размеру (O1) или по скорости (O2)
    или (Ox) и вот еще что если строка длиннее 103 символов
    вываливается ошибка
    .\main.c(22) : fatal error C1060: compiler is out of heap space
    тестил только на MSVC2008
    Code:
    #include <stdio.h>
    #include <boost/preprocessor.hpp>
    
    #define CT_INIT_X2(z,n,text) BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_TUPLE_ELEM(2, 0, text)) \
    	[n]=BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 1, BOOST_PP_TUPLE_ELEM(2, 0, text))) \
    	[n]+(BOOST_PP_IF(BOOST_PP_NOT_EQUAL(n,BOOST_PP_TUPLE_ELEM(2, 1, text)),CT_INIT_MAGIC,0)) \
    	BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(n,BOOST_PP_TUPLE_ELEM(2, 1, text)))
    
    #define CT_INIT_X1(z,n,text) (sizeof(BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 1, text))) == n \
    	&& (BOOST_PP_REPEAT(n, CT_INIT_X2, (text,BOOST_PP_DEC(n)))));
    
    #define def(buf,str) \
    	char buf[sizeof(#str)]; \
    	BOOST_PP_REPEAT_FROM_TO(2, 202, CT_INIT_X1, (buf,str)) 
    
    
    
    #define CT_INIT_MAGIC 3
    
    int main()
    {
    	def(buf, zombie);
    	printf(buf);
    }
    
    Code:
    output:
    }rpelhДля продолжения нажмите любую клавишу . . .
    
    Code:
    int main()
    {
    00401000 55               push        ebp  
    00401001 8B EC            mov         ebp,esp 
    00401003 51               push        ecx  
    00401004 51               push        ecx  
    	def(buf, zombie);
    	printf(buf);
    00401005 8D 45 F8         lea         eax,[buf] 
    00401008 50               push        eax  
    00401009 C6 45 F8 7D      mov         byte ptr [buf],7Dh 
    0040100D C6 45 F9 72      mov         byte ptr [ebp-7],72h 
    00401011 C6 45 FA 70      mov         byte ptr [ebp-6],70h 
    00401015 C6 45 FB 65      mov         byte ptr [ebp-5],65h 
    00401019 C6 45 FC 6C      mov         byte ptr [ebp-4],6Ch 
    0040101D C6 45 FD 68      mov         byte ptr [ebp-3],68h 
    00401021 C6 45 FE 00      mov         byte ptr [ebp-2],0 
    00401025 FF 15 00 20 40 00 call        dword ptr [__imp__printf (402000h)] 
    0040102B 59               pop         ecx  
    }
    0040102C 33 C0            xor         eax,eax 
    0040102E C9               leave            
    0040102F C3               ret              
    
     
  17. greki_hoy

    greki_hoy Member

    Joined:
    4 Mar 2010
    Messages:
    326
    Likes Received:
    57
    Reputations:
    41
    2 slesh вот еще одна реализация через switch
    компиляция быстрая нет ограничения на длинну
    http://pastecode.ru/765b/
     
  18. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Да дело всё в том, что данные должны быть именно как данные, а не код.
    И при надобности я бы их расшифровывал нужной мне функцией.
     
  19. greki_hoy

    greki_hoy Member

    Joined:
    4 Mar 2010
    Messages:
    326
    Likes Received:
    57
    Reputations:
    41
    интересно а такой сценарий будет работать
    Code:
    int main()
    {
    	/*
    	 * 1) добавлять $ в начало зашифрованных строк
    	 * в enc смотреть если $ сменился на & значит 
    	 * уже была расшифрована просто возвращать адрес
    	 * иначе декодить менять $ на & и возвращать адрес
    	 */
    	
    	char buf[]={enc("$crypt")};
    	puts(buf);
    	call(enc("$zombie"));
    	
    	/*
    	 * 2) включить генерацию релоков получим все ссылки 
    	 * на наши строки в Post-Build Event открываем 
    	 * бинарик пробегаемся по всем адресам смотрим 
    	 * если первый байт 0x24 наш $ шифруем 
    	 * до терминатора (сколько микросекунд это займет ?)
    	 */
    }