일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Windows
- 리뷰
- CS
- 티스토리
- 백준
- 함수
- 지식나눔강좌
- 김성엽
- 알고리즘
- tipssoft
- Kotlin
- 배열
- 포인터
- Win32
- c++
- Javascript
- Tips프로그래밍강좌
- c#
- 프로그래밍
- Programming
- c
- doit코틀린프로그래밍
- Visual Studio
- Direct2D
- 문법
- Tips강좌
- VS ERROR
- Desktop
- 연산자
- 이지스퍼블리싱
- Yesterday
- Today
- Total
목록리버싱 (13)
F.R.I.D.A.Y.
test를 쓰는 경우도 있고, cmp를 쓰는 경우도 있다. 비슷하면서 약간 다르다. cmp는 전자의 값에서 후자의 값을 뺀다.cmp a, b>> a - b == 0 test는 전자와 후자의 값을 비트 and 연산 한다.test a, b>> a & b == 0 때문에, test는 비트 and 특성상 양쪽의 값이 모두 0일 경우에만 0이 반환되므로 양 값을 모두 확인할 수 있다. 참고>> http://egloos.zum.com/dal4segno/v/438860
프롤로그, 에필로그 프로그램에서 함수를 사용하면 함수를 이용하기 위해 파라미터와 관련 구조를 쌓는 과정이 필요하다. 이 과정을 프롤로그, 에필로그라고 말한다. 여기서, 프롤로그는 함수 시작에서 구조를 쌓는 과정을 말하고, 에필로그는 함수의 구조를 파괴하는 것을 말한다. 스택 프레임 어떤 절차(또는 함수)의 호출에 따라 그와 관계되는 모든 데이터를 저장해두는 스택 영역. 호출된 프로그램의 프레임은 스택상에 순차 겹쳐 쌓여지고, 나중에 그 순서대로 꺼내진다. 참고>> http://pang2h.tistory.com/59>> https://terms.naver.com/entry.nhn?docId=759295&cid=50324&categoryId=50324 레지스터 문서 분할 : http://pang2h.tist..
#include main() { int x; int y; x = 10; y = x - 5; if( x > y ) { printf( "x의 값이 y보다 큽니다." ); } else { printf( "x의 값이 y보다 작습니다." ); } } 위 코드를 분석한다. 처음 IDA에 올리면 아래 코드가 나온다. 보면, 분기구문이 있으므로, if문이 있다고 보여진다. 코드를 보면 일단, 10과 5를 넣는것을 알 수 있다. (실수로 [401093]까지 블럭을 씌워야 하는데, 못했다. 귀찮아서 수정은 안함) 이 코드에서 ecx 레지스터와 스택에 들어있는 값을 비교한다. 즉, 스택에 들어있는 10과 5를 비교한다고 볼 수 있다. cmp 명령어는 결과가 -가 나오면 CF가 1로, 0이면 ZF가 1로 설정된다. 따라서 일..
콘솔 프로그램의 패스워드를 찾는 리버싱인듯 하다. 쭉 돌아보면 [9139B]에서 main을 콜한다. 이후에 값을 입력하게 되면 이 위치에서 문자열의 길이를 판단한다. 14개의 문자를 입력하면 기본적으로 [Sure ! Nice]가 나오고 프로그램이 종료된다. 단, 종료 코드는 -8이 나오므로 정상적인 패스워드는 아니라는 소리다. fake를 넣어서 이것으로 리버싱이 끝났다고 착각하도록 만들고 있다. F8을 눌러 [910DB]까지 내려오게 되면 여기서부터 데이터를 체크한다.cmp byte ptr ss: [ebp-N], N 에서 뒤에 숫자를 ASCII 변환을 해보면 다음과 같다. 즉, 이 프로그램의 패스워드는R3versE_is_FuN 이다. 이렇게 찾은 패스워드를 입력하면 프로그램은 다음과 같이 작동한다. 리버..
#include #define X 1 #define PI 3.141592 main() { double z; z = X + PI; printf( "%f", z ); } 위 코드를 분석한다. IDA로 돌리면 아래와 같은 코드가 나온다. var_8의 경우에는 IDA가 분석을 실행하며 발생하는 IDA 변수로 바라볼 수 있다. movsd 명령어는 DWORD 기준으로 복사를 시행한다. mov 명령어로도 충분이 이동이 가능하지만, CPU에 존재하는 명령어를 통해 속도를 최적화하기 위해 사용한다. xmm0은 CPU상에 128bit의 레지스터를 의미한다. 자세한 내용은 다음 참고. 이렇게 데이터를 처리하는 이유은 현재 컴퓨터에서 정수의 저장방식과 실수를 저장할 때 사용하는 부동소수점의 저장방식에 차이가 있기 때문이다. ..
#include main() { int x; int y; int z; x = 1; y = 2; z = x + y; printf( "%d", z ); } 이번엔 위 코드를 분석한다. IDA로 돌리면 아래 이미지와 같은 화면이 나온다. push 3push offset _Format 이 두 줄의 코드로 3과 _Format이 가리키는 주소를 스택에 쌓는다. 그러면 스택에는 아래 이미지와 같이 데이터가 쌓이게 된다. 이후 _printf 함수가 호출된다.add esp, 8xor eax, eax 두 줄의 코드를 통해 호출한 함수를 정리한다. 이제 간단히 의사 코드를 작성하면 아래와 같아진다. #include int main(void){ printf(_Format, 3); return 0; } _Format은 C001..
#include main() { printf( "오늘부터 나는 C 프로그래머!" ); } 위 코드를 IDA로 분석하면 아래와 같은 ASM이 나온다. 이 코드를 역분석 하는 것이 C001의 문제이다. offset _Format에서 offset은 명령어로 다음 기능을 수행한다. offset>> 전역 변수의 주소를 구한다. 여기서 _printf 아래의 두줄은 주석의 설명과 같다.add esp, 4 ; esp값을 4를 더하고 (즉, 프로그램 시작의 bp를 지운다. )xor eax, eax ; eax를 xor을 해서 0으로 바꾼다. 따라서 프로그램 코드를 작성할 당시 전역 변수가 저장된 주소를 찾아준 후, 스택에 쌓는 작업을 [401010]이 작업한다고 볼 수 있다.이후, _printf를 실행하므로 기본 구조는 ..
CPU는 연산속도가 굉장히 빠르다. 하드디스크보다 SSD가, SSD보다 메모리(RAM, 램)가 빠르다는 것은 일반적으로 알고 있다. 그러나 CPU는 메모리 속도를 훨~씬 뛰어넘는다. CPU는 연산을 위해 자체 메모리를 가지고 있는데 이 메모리는 용량은 미칠듯이 작으면서 가격은 미칠듯이 높아서 차선책으로 현재의 램이 사용되는 것이다. 레지스터는 다음으로 나눌 수 있다.>> 범용 레지스터>> 세그먼트 레지스터>> 플래그 레지스터>> 명령 포인터 레지스터 레지스터는 XL, XH 등으로 분할해서 접근이 가능하다. XL과 XH를 모두 접근하고자 하면 XX라고 하면 된다.범용 레지스터EAX 주 누산기. 산술 연산에 사용, 기본적으로 산술된 값을 저장한다.EBX DS 세그먼트의 포인터를 주로 저장한다. ESI나 ED..
프로그램을 처음 실행하면 위와 같은 윈도우가 화면에 나타난다. [F9]를 누르면 [401000]으로 이동하지 않고 [4013C0]으로 이동하는데 프로그램이 시작하기 전, 사전 초기화 작업으로 보인다.메모리 주소가 [4013C0]이다. 확인해보면 각 메모리 주소는 다음 행동으로 예측할 수 있다. [401000] ~ [401076]>> 윈도우 클래스 설정, 등록과정 [40107C] ~ [4010A7]>> 윈도우 생성 과정 [4010AD] ~ [4010B3]>> 생성된 윈도우 출력 [4010E2] ~ [4010FB]>> 프로그램의 이벤트에 따른 행동을 위해 프로그램을 종료시키지 않음 프로그램 이벤트는 메모리주소 [401120]으로 시작하는 함수단에서 처리하는 것으로 보인다. WNDCLASS의 WndProc 부..