이걸 가지고 얼마나 삽질을 했던가...
msvcrt.printf ("Count : %d", count++)
msvcrt.printf("Count : %d" % count++)
도대체 무엇이 틀린까 고민하던 끝에 ollydbg를 통해서 스택 구조를 확인 해 보았다.
이런...이런....된장~~!!
겁나 삽질 할 필요도 없는 내용이 나오게 되었다.
msvcrt.printf ("Count : %d", count++)
# CPU Stack
# Address Value ASCII Comments
# 0021FB0C /1D1ADC9A ; RETURN to _ctypes_pyd.1D1ADC9A
# 0021FB10 |01A16BA4 ; ASCII "Loop iteration %d!"
# 0021FB14 |00000002 ;
msvcrt.printf("Count : %d" % count++)
# CPU Stack
# Address Value ASCII Comments
# 0021FB20 /1D1ADC9A ; RETURN to _ctypes_pyd.1D1ADC9A
# 0021FB24 |019A88A4 ; ASCII "Loop iteration 0!"
자, 보이시는가?
C방식으로 호출 할 때는 ESP + 0x08 위치에 2번째 아큐먼트 값이 들어가고,
python 방식으로 호출할 때는 ESP + 0x04 위치에 이미 만들어진 아큐먼트 값이 들어가 있다.
따라서, python pydbg를 이용한 예제에서 아무리 ESP+0x08의 값을 가지고 삽질을 해봐야 답이 나오지 않는다.
그래서 아래와 같이 수정을 해야 한다.
(해당 내용은 나보다 먼저 고민하고 작성한 중국인이 있었다. 그 분에게 다시 한번 감사를 표한다.
thank you so much wanglong1982 - http://shellcodes.sinaapp.com/articles/date/2013/05)
# python 방식(printf "%s" % buff)에서는 ESP+0x04가 인자의 위치이다.
# CPU Stack
# Address Value ASCII Comments
# 0021FB20 /1D1ADC9A ; RETURN to _ctypes_pyd.1D1ADC9A
# 0021FB24 |019A88A4 ; ASCII "Loop iteration 0!"
# 또한, 인자는 이미 합쳐진 내용이 표현되며, c 호출 방식과 차이가 난다.
# ESP + 0x04 인자의 주소를 읽어 드림.
parameter_addr = dbg.context.Esp + 0x04
print ('context EIP : 0x%08x' % dbg.context.Eip)
print ('context ESP : 0x%08x' % dbg.context.Esp)
print ('parameter address : 0x%08x' % parameter_addr)
counter = dbg.read_process_memory(parameter_addr, 4)
# read_process_memory는 패킹된 바이너리 문자열을 리턴한다.
# 따라서 그것을 사용하기 전에 먼저 언팩을 수행해야 한다.
string_addr = struct.unpack("L", counter)[0]
# "Loop iteration %d!\n" = 20byte
# 다 문자열 이기 때문에 공백까지 포함해서 20byte 계산
str_len = 15 + 3 + 2
# 문자열이 존재하는 위치를 알았으니, 해당 문자열의 주소에 문자열 사이즈 만큼 얻어옮.
counter_string = dbg.read_process_memory(string_addr, int(str_len))
counter_string = struct.unpack(str(str_len) + "s", counter_string)[0]
# "!\n" 내용은 필요 없으므로 제거.
counter_string = counter_string.split("!\n")[0]
# counter_string 에서 앞에서 15 자리까지 버리고 다음부터 자리 가지고 옴.
counter = counter_string[15:]
print "Counter: %d" % int(counter)
# 랜덤한 숫자를 생성
random_counter = str(random.randint(1, 100))
# 생성된 숫자를 "Loop iteration" 이후 주소에 기록
dbg.write_process_memory(string_addr + 0x0F, random_counter)
위와 같은 코드를 이용하면 아래와 같은 내용을 얻을 수 있다.
C로 호출하는 방식은 책에 있는 내용을 그대로 인용하면 되므로 추가적으로 언급하지 않겠다.
python 형태로 호출할 때 유념하고, 또한 python 형태로 호출하더라도 수정 될 수 있는 내용이 이므로 포기하지 말고
마무리 짓길 바란다.
'프로그래밍 > Python' 카테고리의 다른 글
win7 에서 pydbg 이용한 snap 찍기 (0) | 2013.07.29 |
---|---|
Windows 7에서 pydbg 설치 하기 (0) | 2013.07.26 |
Windows 7에서 GetSystemInfo 사용하기 (0) | 2013.07.25 |
Windows 7에서 사용하는 파이선 디버거(W7PD) (0) | 2013.07.24 |
python 3.x has_key 없어짐!!!! (0) | 2013.07.23 |