파이썬(Python) 모듈을 python으로 직접 실행하는 경우만 실행되도록 하려면 아래와 같이 if __name__ == "__main__" 으로 묶어주면 됩니다. ^^

if __name__ == ""
    print "이 부분은 python a.py와 같이 직접 실행될 때만 호출됩니다"


파이썬 코드를 작성한 뒤에 실행했을 때 SyntaxError:Non-ASCII charactor… 가 발생하는 경우는 파일의 가장 위에 아래처럼 인코딩 정보를 표시해주면 됩니다.

# -*- coding: cp949 -*-      <== 윈도우에서 기본 설정으로 저장한 파일
# -*- coding: utf-8 -*-      <== UTF8 인코딩으로 저장한 파일


자꾸 까먹어서 이제는 코드 조각들을 웹에다가 올려야겠네요. ㅠㅠ 사용하는 주 언어가 아니다보니 매번 찾아보기도 귀찮고… ㅠㅠ

그럼 좋은 하루 되세요 ^^


ps) 파이썬 소켓에 대한 정보를 원하신다면 http://docs.python.org/2/library/socket.html 를 참고하세요 ^^

 점프 투 파이썬의 저자이신 박응용님께서 책의 내용을 공개해 놓으셨습니다. 책 내용은http://wikidocs.net/mybook/read/library?pageid=1 에서 보실 수 있습니다. 테스트 주도 개발(TDD)에 대한 내용도 있더군요. 관심 있으신 분은 한번쯤 들러보시면 좋을 것 같습니다.

사용자 삽입 이미지

 예전에 파이썬 공부할때 많이 봤던 책인데, 이렇게 웹에서 보게되니 반갑네요. ㅜ_ㅜ)/~ 박응용님 블로그(http://tdd.or.kr/tddlog/)에도 잠깐 들렀는데... 참 대단하신 분인것 같습니다. 직장생활 하시면서 저렇게 많은 웹서비스를 개발하다니... 역시 하기나름인 것 같습니다(저도 열심히 @0@)/`!!!).

 파이썬 만세~ >ㅁ<)/~!!~

 

05 스프링노트(Springnote) API

원문 : http://nakada.springnote.com/pages/400945

 

들어가기 전에

 

0.시작하면서...

 파이썬(Python)에서 스프링노트에 접근하는 내용을 스크랩했다.

 

1.스크랩 내용

  • 참고한 소스 
    • 하늘모자님이 작성하신 python에서 스노피 소스 읽고 쓰기 http://doc.springnote.com/pages/313680 를 참고하여 8월 1일부터 바뀐 API 인증에 맞게 하였습니다.
    • ias 님이 루비로 작성하신 스노피 소스 읽고 쓰기 http://dev.springnote.com/pages/3364 를 참고하여 새로 바뀐 인증방식에 적용 하였습니다.
  • 변화된 사항 
    • 하늘모자님의 소스에서 바뀐 부분은 HTTPS 을 이용한 인증부분과 쉘상에서 입력받을때 \n 을 무조건 없애던것을 수정하였으며, 탭을 공백 4개로 표시하게 하였습니다.
    • ias 님의 소스에서와 같이 파일을 read 하여 data 를 작성하는것은 src=sys.stdin.read() 부분만 src = open('파일이름').read() 로 해주시면 됩니다.
  • 특이사항 
    • from xml.etree.ElementTree import XML 부분의 경우 python 2.5 이상에서만 됩니다. 굳이 필요하지 않으므로 해당 부분을 제거하고 소스에서  print XML(r).findtext('source')  부분만 그냥 print r 로 해도 되며 다른 xml 모듈을 사용해서 가공하시면 됩니다.
    • multipart/form-data 를 통한 파일 첨부는 제 능력 부족으로 구현하지 못하고 있습니다. 정보 있으시면 연락주세요
    • 아직 잘 작성하지 못해서 좋은 정보나 관련된 정보 주시면 감사하게 받겠습니다. 연락은 제 블로그나 메일로 주세요
  • 연락처 

 

  1. #!/usr/bin/python
  2. import sys
  3. from ConfigParser import SafeConfigParser
  4. import base64
  5. import urllib
  6. import httplib
  7. import cgi
  8. from xml.etree.ElementTree import XML
  9. class SpringNote:
  10.     def __init__(self):
  11.         self.config = SafeConfigParser()
  12.         self.config.read('spring.conf')
  13.         open_id = self.config.get('springnote','open_id')
  14.         user_key = self.config.get('springnote','user_key')
  15.         app_key = self.config.get('springnote','app_key')
  16.         username = urllib.quote(open_id)
  17.         passwd = urllib.quote('%s.%s' % (user_key, app_key))
  18.         self.basic_auth = 'Basic %s' % base64.b64encode('%s:%s' % (username, passwd))
  19.     def httpReq(self, method, uri, data = None):
  20.         HOSTNAME = 'api.springnote.com'
  21.         conn = httplib.HTTPSConnection(HOSTNAME)
  22.         conn.putrequest(method, uri)
  23.         conn.putheader('Authorization', self.basic_auth)
  24.         if data :
  25.             conn.putheader('Content-Type','application/xml')
  26.             conn.putheader('Content-Length', len(data))
  27.         conn.endheaders()
  28.         if data :
  29.             conn.send(data)
  30.         response = conn.getresponse()
  31.         r = response.read()
  32.         conn.close()
  33.         print XML(r).findtext('source')
  34.     def getPage(self, page_id):
  35.         self.httpReq('GET','/pages/%s.xml' % page_id)
  36.     def putPage(self, page_id):
  37.         print 'input page content:'
  38.         src = sys.stdin.read()
  39.         src_html = '<p>%s</p>' % cgi.escape(src).replace('\r', '').replace('\t','&nbsp;'*4).replace('\n', '</p>\n<p>').replace('<p></p>','<p>&nbsp;</p>')
  40.         data = "<page><source>%s</source></page>" % cgi.escape(src_html)
  41.         self.httpReq('PUT', '/pages/%s.xml' % page_id, data)
  42.     def main(self, cmd, arg):
  43.         if cmd == 'get':
  44.             self.getPage(arg)
  45.         elif cmd == 'put':
  46.             self.putPage(arg)
  47. if __name__ == "__main__":
  48.     SpringNote().main(sys.argv[1], sys.argv[2])

 

이 글은 스프링노트에서 작성되었습니다.

 백업을 위해 하드디스크에 여유공간을 확보할 일이있어서 어떤 파일을 삭제할까 한참을 고민했습니다. 시디 이미지를 지울까 고민하다가, 문득 빌드 과정에서 나오는 파일의 크기가 크다는 것이 떠올랐습니다. >ㅁ<)/~!!

 처음에는 윈도우의 검색기능을 이용해서 지우기를 했었는데, 의외로 시간도 많이 걸리고 불편하더군요. 그래서 간단히 파이썬으로 코드를 짜봤습니다. ExtList에 다른 확장자를 추가하면 기타 파일도 삭제를 할 수 있습니다.

 파이썬의 저력을 다시 한번 느꼈습니다. 아주 금방되더군요. ^^;;; 이걸 C 언어로 짰어도 이렇게 빨리 끝났을까요? 한 10분정도 걸렸는데... ㅡ_ㅡa...

 아래는 지워주는 코드입니다.


 파이썬 만세~~!! >ㅁ<)/~~!!!

ps) OS에 대한 내용은 http://docs.python.org/lib/os-file-dir.html 를 참고하세요. ^^


 파이썬을 공부하고 싶으시다면 http://www.diveintopython.org/ 사이트를 한번 들려보세요. 책 Dive Into Python 의 내용을 PDF 및 각가지 포맷으로 무료 제공하고 있으며, 소스코드까지 주는군요. ^ㅡ^)/~

 후배가 발견한 사이트인데, 어디서 이런 사이트를 찾는지 모르겠군요(그놈 참 능력 좋네~ ㅎㅎ). 세컨트 프로그래밍 언어로 파이썬을 쓰시는 분이 많을꺼라 생각하는데, 특히 C/C++을 쓰시는 분들이라면 더욱 그럴꺼라 생각합니다.
 
 제 개인적인 소견으로 무척이나 C/C++에 가깝더군요. 그러면서도 유연하고 C의 라이브러리를 그대로 당겨쓸 수 있는 것이 아주 매력적인 언어였습니다. 물론 GUI 프로그래밍에는 좀 많이 약했지만... ^^;;; 텍스트 처리에는 굉장한 능력을 가진듯 보였습니다.

 한참 파이썬 프로그래밍을 하다, 새로운 NDS 홈브루를 개발하다보니 다시 C/C++로 돌아왔네요. 어느정도 정리되고나면 파이썬 공부를 다시 해야겠습니다. ^^
 와~ 정말 파이썬으로 안되는 것이 없군요. 처음에 파이썬을 접했을 때 많은 모듈이 있는 걸 알았지만 주로 웹이나 텍스트 처리, DB쪽 관련이었습니다. 특히 파이썬으로 GUI 프로그래밍을 하려면 다른 언어와 섞어 사용하는 것으로 알고 있어서 GUI 관련 쪽은 약하다고 생각했는데... 파이썬으로 GPU를 컨트롤 할 수 있네요. ^^;;;
 원문은 http://www.hackszine.com/blog/archive/2007/10/pygpu_write_software_for_the_g.html 에서 볼 수 있습니다.

 이미지 프로세싱 관련 처리를 GPU에게 넘겨서 빨리 처리할 수 있도록 해준다는 것 같은데 GIMP에서 사용하는 모듈인 듯하네요. ^^

 파이썬~ 정말 멋진 언어인 것 같습니다. ^^

04 진보된 DLL 디스어셈블러 만들기

원문 :  http://kkamagui.springnote.com/pages/389711

 

들어가기 전에...

 

 요전에 DLL 디스어셈블리어 프로그램을 하나 만들었다. 그런데 단순한 디스어셈블러였을 뿐, 실제 분석에 필요한 뭔가가 없었다. 보통 분석할 때(내가.. ㅡ_ㅡ;;; 다른 사람은 모르겠음...) 함수 단위로 call, jmp 하는 부분 위주로 따라가면서 분석하는데, 그러한 기능이 없었다.

 그래서 이러한 함수 분석 기능을 추가하여 JMP, JL, JE 등등과 같은 JMP와 call을 분석해서 따라갈 수 있는 것은 따라가 주도록 만들었다. 아직은 파이썬에 익숙하지 않아서 시간이 좀 걸렸지만... 하면서도 나름 재미있었다는.. ㅠ_ㅠ...

 아래는 코드이다.

  1. # -*- coding: cp949 -*-
    from distorm import Decode, Decode16Bits, Decode32Bits, Decode64Bits
    # c관련 함수를 사용하기위해 처리
    from ctypes import *
    import ctypes
  2. g_assemblyBuffer = [];
    g_gotoBufferArray = [];
  3. # Disassembly를 수행하는 함수
    def Disassembly( intAddress, curLevel, maxLevel ):
        buffer = ctypes.c_buffer( 4096 );
        libc.memcpy( buffer, intAddress, 4096 );
     
        l = Decode(intAddress, buffer, Decode32Bits)
        for i in l:
            # 아래와 같은 형식으로 출력된다.
            # 0x7c8309e1 8bff                 MOV EDI, EDI
            buffer = "0x%08x %-20s %s" % (i[0], i[3].upper(),  i[2])
            g_assemblyBuffer.append( buffer );
           
            # 만약 Jmp나 call 같은 명령이면 그 뒤에 오는 주소를 넣는다.
            if ( "J" in i[ 2 ] or "CALL" in i[ 2 ] ) and \
               ( "0x" in i[ 2 ] and "+" not in i[ 2 ] and "-" not in i[ 2 ] and \
                '*' not in i[ 2 ] and '/' not in i[ 2 ] ) and \
                curLevel < maxLevel:
                index = i[ 2 ].find( " " );
                stringAddr = i[ 2 ][ index + 1 : ];
                g_gotoBufferArray.append( [ curLevel + 1, stringAddr ] );
                #print "gotoBufferAdd", buffer;
               
            # 만약 ret거나 JMP 이면 그만 한다.
            if ( "RET" in i[ 2 ] ) or "NOP" in i[ 2 ]:
                g_assemblyBuffer.append( " " );
                return ;
  4. # Hex값을 Int로 바꾼다.
    def HexAddrToIntAddr( address ) :
        intAddress = 0;
        address = address[ 2 : ];
        for i in address :
            intAddress = intAddress << 4;
            if ord( i ) >= ord( '0' ) and ord( i ) <= ord( '9' ) :
                intAddress += int( i );
            else :
                intAddress += ( ord( i ) - ord( 'a' ) + 10 );
        return intAddress;
  5. # Indirect Addressing을 처리 함수
    def GetIndirectValue( address ):
        intAddress = 0;
        intAddress = HexAddrToIntAddr( address );
       
        #print "Indirect Address[%x]" % intAddress;
        buffer = ctypes.c_buffer( 4 );
       
        libc.memcpy( buffer, intAddress, 4 );
        #little Endian 이므로 역순으로 들어가있다. 이것을 바꿔준다.
        value = 0;
        mulValue = 0x00000001;
        for i in buffer :
            value += ( ord( i ) * mulValue );
            mulValue = mulValue << 8;
            #print "%x" %ord( i );
  6.     #print "%x" %value;
        return value;

  7. # 이미 Disassemby한 Address 인가 확인
    def IsAlreadyDisassembly( address ):
        for i in g_assemblyBuffer:
            if address in i[ : 10 ] :
                return 1;
        return 0;
  8. # c 런타임 라이브러리를 가지고 있음
    libc = cdll.msvcrt;
  9. dllName = raw_input( "DLL Name : " );
    functionName = raw_input( "Procedure Name : " );
    maxLevel = input( "Analysis Level( 0 ~ 20 ) : " );
  10. # 함수를 찾는다.
    dll = windll.LoadLibrary( dllName );
    functionAddress = dll.GetProcAddress( dll._handle, functionName );
  11. # 시작 Address를 넣는다.
    g_gotoBufferArray.append( [ 0, "0x%x" %functionAddress ] );
  12. for i in g_gotoBufferArray :
        [ level, stringAddress ] = i;
  13.     if '[' in stringAddress :
            intAddress = GetIndirectValue( stringAddress[ 1 : -1 ] );
            g_assemblyBuffer.append( "==============Level[%d] %s 0x%x============\n" \
                %( level, stringAddress, intAddress ) );
        else :
            intAddress = HexAddrToIntAddr( stringAddress );
            g_assemblyBuffer.append( "==============Level[%d] %s============\n" \
                %( level, stringAddress ) );
           
        # 점프하는 주소가 이미 Disassembly 되어있으면 안한다.
        if IsAlreadyDisassembly( "0x%x" %intAddress ) == 1 :
            g_assemblyBuffer.append( "0x%x Is Already Disassembly\n" %intAddress );
            continue;
       
        Disassembly( intAddress, level, maxLevel );
  14. # 출력하는 부분
    file = open( dllName + functionName + ".txt", "w" );
    print "Now Writing....."
    for i in g_assemblyBuffer:
        file.writelines( i + "\n" );
        #print i;
    file.close();
    print "Write Complete....."

 

 이것을 실행하면 DLL 이름과 함수 이름, 그리고 얼마나 깊이 call을 추적할 것인가가 나오는데, call 추적은 3~4 정도가 충분하다.

 아래는 kernel32.dll, OpenProcess, 3으로 함수를 분석한 결과이다. 아주 깔끔하게 잘 분석되었다 @0@)/~!!

==============Level[0] 0x7c8309e1============

0x7c8309e1 8BFF                 MOV EDI, EDI
0x7c8309e3 55                   PUSH EBP
0x7c8309e4 8BEC                 MOV EBP, ESP
0x7c8309e6 83EC 20              SUB ESP, 0x20
0x7c8309e9 8B45 10              MOV EAX, [EBP+0x10]
0x7c8309ec 8945 F8              MOV [EBP-0x8], EAX
0x7c8309ef 8B45 0C              MOV EAX, [EBP+0xc]
0x7c8309f2 56                   PUSH ESI
0x7c8309f3 33F6                 XOR ESI, ESI
0x7c8309f5 F7D8                 NEG EAX
0x7c8309f7 1BC0                 SBB EAX, EAX
0x7c8309f9 83E0 02              AND EAX, 0x2
0x7c8309fc 8945 EC              MOV [EBP-0x14], EAX
0x7c8309ff 8D45 F8              LEA EAX, [EBP-0x8]
0x7c830a02 50                   PUSH EAX
0x7c830a03 8D45 E0              LEA EAX, [EBP-0x20]
0x7c830a06 50                   PUSH EAX
0x7c830a07 FF75 08              PUSH DWORD [EBP+0x8]
0x7c830a0a 8D45 10              LEA EAX, [EBP+0x10]
0x7c830a0d 50                   PUSH EAX
0x7c830a0e 8975 FC              MOV [EBP-0x4], ESI
0x7c830a11 C745 E0 18000000     MOV DWORD [EBP-0x20], 0x18
0x7c830a18 8975 E4              MOV [EBP-0x1c], ESI
0x7c830a1b 8975 E8              MOV [EBP-0x18], ESI
0x7c830a1e 8975 F0              MOV [EBP-0x10], ESI
0x7c830a21 8975 F4              MOV [EBP-0xc], ESI
0x7c830a24 FF15 0C11807C        CALL [0x7c80110c]
0x7c830a2a 3BC6                 CMP EAX, ESI
0x7c830a2c 5E                   POP ESI
0x7c830a2d 0F8C B7710000        JL 0x7c837bea
0x7c830a33 8B45 10              MOV EAX, [EBP+0x10]
0x7c830a36 C9                   LEAVE
0x7c830a37 C2 0C00              RET 0xc
 
==============Level[1] [0x7c80110c] 0x7c93dd7b============

0x7c93dd7b B8 7A000000          MOV EAX, 0x7a
0x7c93dd80 BA 0003FE7F          MOV EDX, 0x7ffe0300
0x7c93dd85 FF12                 CALL [EDX]
0x7c93dd87 C2 1000              RET 0x10
 
==============Level[1] 0x7c837bea============

0x7c837bea 50                   PUSH EAX
0x7c837beb E8 7B17FDFF          CALL 0x7c80936b
0x7c837bf0 33C0                 XOR EAX, EAX
0x7c837bf2 E9 3F8EFFFF          JMP 0x7c830a36
0x7c837bf7 90                   NOP
 
==============Level[2] 0x7c80936b============

0x7c80936b 8BFF                 MOV EDI, EDI
0x7c80936d 55                   PUSH EBP
0x7c80936e 8BEC                 MOV EBP, ESP
0x7c809370 56                   PUSH ESI
0x7c809371 FF75 08              PUSH DWORD [EBP+0x8]
0x7c809374 FF15 6C10807C        CALL [0x7c80106c]
0x7c80937a 8BF0                 MOV ESI, EAX
0x7c80937c 56                   PUSH ESI
0x7c80937d E8 2EFFFFFF          CALL 0x7c8092b0
0x7c809382 8BC6                 MOV EAX, ESI
0x7c809384 5E                   POP ESI
0x7c809385 5D                   POP EBP
0x7c809386 C2 0400              RET 0x4
 
==============Level[2] 0x7c830a36============

0x7c830a36 Is Already Disassembly

==============Level[3] [0x7c80106c] 0x7c93fb3d============

0x7c93fb3d 6A 08                PUSH 0x8
0x7c93fb3f 68 78FB937C          PUSH 0x7c93fb78
0x7c93fb44 E8 79F2FFFF          CALL 0x7c93edc2
0x7c93fb49 64 A1 18000000       MOV EAX, FS:[0x18]
0x7c93fb4f 85C0                 TEST EAX, EAX
0x7c93fb51 74 11                JZ 0x7c93fb64
0x7c93fb53 8365 FC 00           AND DWORD [EBP-0x4], 0x0
0x7c93fb57 8B4D 08              MOV ECX, [EBP+0x8]
0x7c93fb5a 8988 F40B0000        MOV [EAX+0xbf4], ECX
0x7c93fb60 834D FC FF           OR DWORD [EBP-0x4], -0x1
0x7c93fb64 FF75 08              PUSH DWORD [EBP+0x8]
0x7c93fb67 E8 1D000000          CALL 0x7c93fb89
0x7c93fb6c E8 91F2FFFF          CALL 0x7c93ee02
0x7c93fb71 C2 0400              RET 0x4
 
==============Level[3] 0x7c8092b0============

0x7c8092b0 8BFF                 MOV EDI, EDI
0x7c8092b2 55                   PUSH EBP
0x7c8092b3 8BEC                 MOV EBP, ESP
0x7c8092b5 56                   PUSH ESI
0x7c8092b6 57                   PUSH EDI
0x7c8092b7 64 A1 18000000       MOV EAX, FS:[0x18]
0x7c8092bd 8B75 08              MOV ESI, [EBP+0x8]
0x7c8092c0 8BF8                 MOV EDI, EAX
0x7c8092c2 A1 C446887C          MOV EAX, [0x7c8846c4]
0x7c8092c7 85C0                 TEST EAX, EAX
0x7c8092c9 0F85 20090300        JNZ 0x7c839bef
0x7c8092cf 3977 34              CMP [EDI+0x34], ESI
0x7c8092d2 0F85 43040000        JNZ 0x7c80971b
0x7c8092d8 5F                   POP EDI
0x7c8092d9 5E                   POP ESI
0x7c8092da 5D                   POP EBP
0x7c8092db C2 0400              RET 0x4

 

 역시나 오늘도 파이썬 만쉐 @0@)/~!!

이 글은 스프링노트에서 작성되었습니다.

03 DLL 디스어셈블러 만들기

원문 : http://kkamagui.springnote.com/pages/388049

 

들어가기 전에...

 

 항상 분석을 하면 노가다가 많고 일일이 손으로 클릭을 해가면서 또는 눈으로 찾아가면서 분석을 해야 했다. 내가 원체 UI에 별로 관심이 없다보니 UI의 수준은 당연 극악의 콘솔형태... 물론 생긴건 GUI다.(그만큼 UI가 엉망이라는.... ㅡ_ㅡ;;;). 언젠가 한번 DLL 분석 툴을 파이썬으로 만들면 재미있겠다고 생각했는데... 파이썬용 디스어셈블러 자료는 찾아놓고 실제로 DLL을 파이썬으로 당겨야 하는데 엄두가 나지 않았다.

 오늘 잠시 짬을 내서 일하다 잠도 안자고 해봤는데, 의외로 C 함수를 쓰는게 간단하다.

 

DLL 및 C 타입의 변수 등등의 사용

 DLL을 로드해서 사용하는 코드를 C로 만들면 LoadLibrary() 함수를 호출하고 다시 GetProcAddress()를 호출하면 된다. 파이썬에서는 이것을 어떻게 할까? 블로그를 찾아보고 파이썬 마을을 둘러봤더니 ctypes라는 것이 보였다. Python 2.5 버전에서 표준 라이브러리에 포함되어있는 라이브러리라는데, 상당히 C 스타일 적이다.(아래는 Python 문서에 포함된 예제이다.)

  1. >>> from ctypes import *
    >>> print windll.kernel32
  2. <WinDLL 'kernel32', handle ... at ...>
    >>> print cdll.msvcrt
  3. <CDLL 'msvcrt', handle ... at ...>
    >>> libc = cdll.msvcrt

 windll에 보면 kernel32.dll, gdi32.dll 등등의 DLL의 정보를 포함하는 모듈이 들어있음을 알 수 있다. C 런타임 라이브러리도 사용할 수 있는데, cdll.msvcrt를 모듈을 이용하면 C 라이브러리를 사용할 수 있다.

  1. >>> from ctypes import *
    >>> libc.printf
    <_FuncPtr object at 0x...>
    >>> print windll.kernel32.GetModuleHandleA
  2. <_FuncPtr object at 0x...>

 재미있는 부분은 포인터도 사용할 수 있다는 것이다.(크아... 이제 완전 게임 끝났다.. @0@)/~ 이렇게 좋을 수가.. ㅜ_ㅜ)

  1. >>> from ctypes import *
    >>> i = c_int(42)
    >>> pi = pointer(i)
    >>> pi.contents
    c_long(42)

 더 자세한 사항은 파이썬 도움말을 참고하도록 하자.

 

디스어셈블러(Disassember) 모듈

 디스어셈블러 모듈은 파이썬 용으로 따로 개발된게 있다.(어찌나 다행인지.. ㅡ_ㅡ;;; 내가 가지고 있는걸로 파이썬에 붙일려고 했는데, 이렇게 되면 기절한다... ㅡ_ㅡ;;;)

 http://www.ragestorm.net/distorm/ 사이트에 가면 파이썬용 모듈을 받을 수 있고 간단히 pyd파일을 받아서 파이썬이 설치된 Lib 폴더에 넣기만 하면 편하게 사용할 수 있다. 아래는 위 홈페이지에서 설명해 놓은 사용 예제이다.

  1. Note: Save the file in %PYTHONDIR%\Lib\site-packages\
    from distorm import Decode, Decode16Bits, Decode32Bits, Decode64Bits
    l = Decode(0x100, open("file.com", "rb").read(), Decode16Bits)
    for i in l:
     print "0x%08x (%02x) %-20s %s" % (i[0],  i[1],  i[3],  i[2])

 

 

디스어셈블러 작성

 이제 디스어셈블러를 작성할 준비가 모두 끝났다. 이제 이 모듈들을 이용하여 kernel32.dll에 있는 OpenProcess 함수를 디스어셈블리해보자.

  1. # -*- coding: cp949 -*-
    from distorm import Decode, Decode16Bits, Decode32Bits, Decode64Bits
    # c관련 함수를 사용하기위해 처리
    from ctypes import *
    import ctypes
  2. # c 런타임 라이브러리를 가지고 있음
    libc = cdll.msvcrt;
    # kernel32.dll을 여는 여러 방법
    #kernel32 = windll.kernel32;
    kernel32 = windll.LoadLibrary( 'kernel32.dll' );
  3. # OpenProcess를 얻는다.
    openProcessAddress = kernel32.GetProcAddress( kernel32._handle, "OpenProcess" );
  4. # 버퍼를 할당해서 디스어셈블리를 하기위해 버퍼에 넣는다.
    buf = ctypes.c_buffer( 4096 );
    libc.memcpy( buf, openProcessAddress, 4096 );
    #libc.memcpy( buf, 0x7c809b96, 4096 );
  5. l = Decode(openProcessAddress, buf, Decode32Bits)
    for i in l:
        # 아래와 같은 형식으로 출력된다.
        # 0x7c8309e1 (02) 8bff                 MOV EDI, EDI
        print "0x%08X (%02X) %-20s %s" % (i[0],  i[1],  i[3].upper(),  i[2])

 

 소스 코드는 위와 같이 아주 간단하다. 출력 결과는 아래와 같이 깔끔하게 나온다.

0x7C8309E1 (02) 8BFF                 MOV EDI, EDI
0x7C8309E3 (01) 55                   PUSH EBP
0x7C8309E4 (02) 8BEC                 MOV EBP, ESP
0x7C8309E6 (03) 83EC 20              SUB ESP, 0x20
0x7C8309E9 (03) 8B45 10              MOV EAX, [EBP+0x10]
0x7C8309EC (03) 8945 F8              MOV [EBP-0x8], EAX
0x7C8309EF (03) 8B45 0C              MOV EAX, [EBP+0xc]
0x7C8309F2 (01) 56                   PUSH ESI

 

 정말 멋지다.. ㅜ_ㅜ... 이렇게 몇줄 작성하지 않았는데 이런 결과가 나오다니... ㅡ_ㅜ... 정말 환상적이지 않을 수 없다. ㅜ_ㅜ...

 파이썬 만쉐이.. ㅜ_ㅜ...

 

첨부

 

 

TODO

  • 코드 내부에 있는 Jump 및 Call 관련 루틴을 따라가서 분석하는 기능 추가하기

이 글은 스프링노트에서 작성되었습니다.

 01 이글루스에서 덧글 뽑기

원문 :  http://kkamagui.springnote.com/pages/377691

 

들어가기 전에...


 

 오늘로써 파이썬을 배운지 약 하루(24시간??)이 지났다. 파이썬이 아주 편리한 언어임을 뼈저리게 깨닫기에는 충분한 시간이었다. 그래서 내친김에 프로그램을 하나 만들었는데, 그것은 바로 @0@)/~!!! 이글루스에서 덧글 뽑기!!!

 

 간혹 덧글을 확인하러 이글루스에 들어가는데... 이것을 파이썬으로 대체해서 덧글만 뽑는 것이다. @0@)/~!!! 전에 비슷한 것을 VC++로 한적이 있는데... 상당히 긴 코드였다. 하지만.. 파이썬으로 했을때는... ㅠ_ㅠ... 아래 코드가 전부이다.

  1. # -*- coding: cp949 -*-
    import urllib
  2. # euc-kr Text를 utf-8의 형태로 바꾼다.
    def ConvUtf8( buffer ):
        uniText = unicode( buffer, "euc-kr" );
        return uniText.encode( "utf-8" );
  3. # utf-8 Text를 euc-kr의 형태로 바꾼다.
    def ConvEucKr( buffer ):
        uniText = unicode( buffer, "utf-8" );
        return uniText.encode( "euc-kr" );
  4. # 버퍼에서 각 부분을 자른다.
    def ExtractItem( buffer, startTag, endTag ):
        replyStart = ConvUtf8( startTag );
        replyEnd = ConvUtf8( endTag );
       
        #print "개별 추출 함";
  5.     try:
            startIndex = buffer.index( replyStart );
            endIndex = buffer[ startIndex : ].index( replyEnd );
        except:
            return [ buffer, "" ];
       
        if startIndex != -1 and endIndex != -1:
            endIndex = startIndex + endIndex;
            #print "찾음", startIndex, endIndex;
           
            reply = buffer[ startIndex : endIndex + len( replyEnd ) ];
            return [ buffer[ endIndex + len( replyEnd ) : ], reply ];
           
        else:
            #print "찾을 수 없습니다";
            return [ buffer, "" ];
  6.        
    # 메인 코드
    urlHandle = urllib.urlopen( "http://kkamagui.egloos.com" );
    buffer = urlHandle.read();
    # 덧글 블럭만 뽑는다.
    [ buffer, extractBuffer ]= ExtractItem( buffer,"<DIV CLASS=MNTTL>최근 등록된 덧글</DIV>",
                                "<CENTER>");
    #print extractBuffer;
  7. # 개별 덧글을 다 찾는다.
    i = 1;
    while 1:
        print "";
        print i;
  8.     reply = "";
        [ extractBuffer, reply ] = ExtractItem( extractBuffer, "<a href=", "</div>" );
        if( reply == "" ):
            break;
        #print reply;
       
        # 덧글은 아래와 같이 되어있다.
        #<a href="http://kkamagui.egloos.com/3287761#9763213">
        #네 감사합니다 ^^</a><br/><span class="SMALL">by kkamagui at 07/20</span>
        #<br/><div style="margin:12px;"></div>
        item = "";
        [ reply, item ] = ExtractItem( reply, "http", '">' );
        item = item[ : -2 ];
        item = ConvEucKr( item );
        print "PageNumber####", item;
  9.     [ reply, item ] = ExtractItem( reply, "", "<" );
        item = item[ : -1 ];
        item = ConvEucKr( item );
        print "Contents###", item;
  10.     [ reply, item ] = ExtractItem( reply, 'SMALL">', "</span" );
        item = item[ 7 : -6 ];
        item = ConvEucKr( item );
        print "Writer###", item;
        i = i + 1;
  11. i = input( "끝입니다. 아무키나 눌러주세요" );

 뭐 간단히 보면 HTML 특정 부분 파싱이 전부이다. 약간 주의할 점은 utf-8 형태로 HTML 코드가 전송되는데, 이것을 콘솔 화면에 적당히 출력하기위해서 euc-kr로 바꿔주는 부분이 조금 특이하다.

 

 이로써 덧글을 확인하러 블로그에 들어가지 않아도 되게 되었다. ㅠ_ㅠ

 

파이썬 만쉐이 ㅠ0ㅠ)/~!!!

 

이 글은 스프링노트에서 작성되었습니다.

+ Recent posts