기본 콘텐츠로 건너뛰기

11월, 2017의 게시물 표시

리버스엔지니어링바이블 01. 리버스 엔지니어링만을 위한 어셈블리

어셈블리는 한 번에 한가지 동작만을 한다.(더하기, 빼기, 옮기기). 특별히 여러 동작을 수행하는 opcode의 경우 자주사용되는 명령어 sequence를 묶어 하나로 만들어 놓은 것이다. 어셈블리는 익히는 것은 IA(Intel Arhchitecture)-32를 배우는 것을 의미한다. 레지스터는 CPU가 사용하는 변수이지만 사용 용도가 정해져있다. 하지만 바뀔 수도 있고 바꿀 수도 있다. EAX : 산술 계산과 리턴값 저장 EDX : EAX와 비슷하지만 리턴값을 저장하지 않는다. ECX : 루프문의 카운터 EBX : 여분의 레지스터 ESI,EDI : source에서 destination 으로 데이터를 옮기는 연산 바이트 저장 순서를 엔디언이라고 한다. 사람이 읽는 대로 저장하면 빅엔디언, 반대로 저장하면 리틀엔디언 이다. 인텔은 리틀엔디언을 사용한다. 연산은 레지스터 간에만 일어난다. 메모리끼리는 연산을 할 수가 없다. 코드 내에서 __declspec(naked)를 선언하면 컴파일러에 의한 코드를 삽입하지 않는다. 어셈블리 코딩을 할 경우 __asm을 선언한다. 함수 호출지 인자는 오른쪽에서 왼쪽으로 스택에 push된다. 인자가 push 되기 전에 리턴주소를 먼저 push하기 때문에 ebp+4 에는 리턴주소가 위치한다. 함수가 호출되어 지역변수공간을 할당할 때는 sub esp, 50h 와 같은 형태를 띈다. 지역변수는 스택에 할당한 순서대로 들어가기 때문에, 소스코드에서 가장위에 적은 변수가 가장 아래쪽에 쌓인다. 따라서 ebp에 가까울 수록 가장위의 지역변수다. ebp-4는 첫번째 지역변수이다. 가장 아래쪽에 쌓이긴 때문에 +를 통해 뒤쪽의 메모리주소를 가르켜야할꺼같지만, 스택은 메모리에서 메모리에서 반대로 자라기 때문에 -이다.

C++/MFC

클래스는 오프셋을 기반으로 멤버함수를 호출한다. 클래스를 동적으로 생성하는 경우 크기만큼 스택을 움직이는 것이 아니라, 동적 메모리함수를 불러 결과값을 받아와 저장해서 사용한다. 클래스의 멤버함수는 컴파일시에 주소가 결정되기 때문에 함수를 부르는 형태를 보면 객체의 주소값을 받아와 바로 콜하는 형태를 갖는다. 가상함수가 있는 경우 객체의 가장 앞에 Vtable 포인터가 생성된다. C++에서 멤버함수를 호출할 때는, 객체의 포인터인 this 변수가 따라간다. 매번 this가 넘어가기 때문에 묵시적이고, 스택이아니라 레지스터를 통해 넘어간다. IDA에서 __this 가 그 의미이다. gcc 컴파일러의 경우 this가 스택으로 넘어간다. 생성자와 소멸자는 선택 가능한 함수이다. 클래스 생성시 가장 먼저 호출된다. 동적으로 생성될때 동적 메모리 할당의 결과값이 유효하면 생성자 호출, 틀리면 0을 삽입한다. 이 때문에 IDA에서 코드블럭을 보면 좌우로 갈라졌다가 다시 합쳐지는 형태를 갖는다. 소멸자도 마찬가지이다. Vtable은 .rdata 에 저장된다.

이원 - 의자에 어울리는 사람이 되기 위해

의자에 어울리는 사람이 되기 위해  곧추 세운 등뼈 아래로  엉덩이를 엉거주춤 유지해야 하는  이 포즈는 도대체 무엇입니까  각자의 배후를 전적으로 위탁하는 포즈를  우리는 언제부터 배워야 했습니까  의자에 어울리는 사람이 되기 위해  어디부터 구부려야 했습니까  어디를 숙여야 했습니까  의자를 닮기 위해  발을 매단 채 손을 매단 채  이상한 도형이 되어야 했습니다  침묵하고 있는 이 짐승은 언제 달리기 시작하나요  창 밖 난간으로는 발음을 모르는 혀들이 몰려들었습니다  밤의 숲에 가면 뼈의 외침이 나무라는 것을 알게 됩니다  사로잡힌 척 의자에 앉아 우리는 손만 쉴 새 없이 움직입니다  한 끼를 위한 너덜너덜한 손의 동작을 왜 멈출 수 없습니까  항문과 입을 동시에 벌리는 법  우리는 어쩌면 이토록 징그러운 동작을 배웠을까요  의자 손잡이가 비명을 지르고 있는 입이라 해도  고해성사의 순서를 알게 되었다면 그것 또한  사소한 습관이 아니겠습니까  뒷모습이 구겨져 있습니다  깜깜한 곳에 우리는 너무 오래 접혀 있었습니다  그런데 당신  의자와 의자가 대화하는 것을 믿습니까  토하고 말았지요  이런!  의자들끼리는 당황은 하지 않습니다 --------------------------------------------- 놀라운 발상

이규경 - 용기

넌 충분히 할 수 있어. 사람들이 말했습니다. 용기를 내야해 사람들이 말했습니다. 그래서 나는 용기를  내었습니다. 용기를 내서 이렇게 말했습니다. 나는 못해요. ------------------------------- 용기에 대한 인식 전환

안도현 - 스며드는 것

스며드는 것                                                - 안도현 꽃게가 간장 속에 반쯤 몸을 담그고 엎드려 있다 등판에 간장이 울컥울컥 쏟아질 때 꽃게는 뱃속의 알을 껴안으려고 꿈틀거리다가 더 낮게 더 바닥 쪽으로 웅크렸으리라 버둥거리렸으리리 버둥거리다가 어찌할 수 없어서 살 속에 스며드는 것을 한때의 어스름을 꽃게는 천천히 받아들였으리라 껍질을먹먹해지기 전에 가만히 알들에게 말했으리라 저녁이야 불 끄고 잘 시간이야 --------------------------- 비유보소 천재다 천재

토마스 커루(Thomas Carew) - 가난한 자의 허세

가난한 자의 허세 가난하고 궁핍한 가엾은 이여, 어찌주제넘게도 하늘의 한자리를 요구하는가. 초라한 오두막이나 통 속에 살고 거저 내리쬐는 햇볕 속이나 그늘진 샘터에 앉아 풀뿌리와 나물로 연명하여 게으르고 학자인 체하는 미덕을 기른다고 해서, 그래서 그러는 겐가. 그곳에서 그대의 오른손은 미덕이 만개하여 풍성한 마음에서 인정 많은 열정을 뜯어내고 본성을 타락하게 하여 감정을 마비시키고 있네. 그리고 고르곤이 했듯이, 활기 넘치는 인간을 돌로 바꾸어 놓는구먼. 우리는 절박함에 따른 그대의 절제나 기쁨도 슬픔도 모르는 부자연스러운 어리석음에서 비롯된 침울한 관계는 바라지 않네. 또한 능동적으로 행한 것이 아닌 마지못해 끌어낸 불굴의 용기도 바라지 않지. 평범한 처지에 만족하는 이 비천한 무리들은 그대의 비굴한 천성과 잘 어울리는구먼. 허나 우리가 위대하다 인정하는 미덕은 용감하고 너그러운 행위, 제왕 같은 기품, 만물을 꿰뚫어 보는 신중함, 한없는 관대함, 그리고...

맥스 어만(Max Ehrmann) - 소망(진정 바라는 것)

진정 바라는 것                                                                       -맥스 어만 소란스럽고 바쁜 일상속에서도  침묵 안에 평화가 있다는 사실을 기억하십시오 포기하지 말고 가능한한 모든 사람들과 잘 지내도록 하십시오 조용하면서도 분명하게 진실을 말하고  어리석고 무지한 사람들의 말에도 귀를 기울이십시오  그들 역시 할 이야기가 있을테니까요  목소리가 크고 공격적인 사람들은 피하십시오  그들은 영혼을 괴롭힙니다 자신을 다른 사람들과 비교하면 자신이 하찮아 보이고  비참한 마음이 들수도 있습니다  더 위대하거나 더 못한 사람들은 언제나...

러디어드 키플링(Rudyard Kipling) - 만약에(If)

만약에(If)                                                           -러디어드 키플링 만약 모두가 이성을 읽고 너를 탓할 때 냉정을 유지할 수 있다면 만약 모두가 너를 의심할 때 네 자신을 믿고 그들의 의심마저 이해해줄 수 있다면 만약 기다리면서도 기다림에 지치지 않을 수 있다면 남에게 속더라도, 남을 속이지 않으며 미움을 받더라도, 미워하지 않으며 그러면서도 너무 선량한 척하지도, 너무 현명한 척하지도 않는다면 만약 꿈을 꾸면서도 꿈의 노예가 되지 않을 수 있다면 만약 생각하면서도 생각을 목표로 삼지 않을 수 있다면 만약 성공과 실패를 만나더라도 두 가지를 똑같이 대할 수 있다면...

파일검색프로그램 - 1. 개발 방향 및 담을 내용

  본 포스팅에서  윈도 (Windows) OS에서 파일 검색해주는 프로그램을 만드는 방법에 대해 포스팅하려고 합니다. Everything 이나  UltraSearch 같은 프로그램을 생각하시면 되는데요,  파일검색프로그램을 만드는 방법에도 여러가지 방법이 있겠지만 본 포스팅에서는 앞의 프로그램과 같은 방식으로 윈도우 파일 시스템인 NT 파일시스템을 이용하려고 합니다. NT FileSystem 은 모든  파일의 정보를 담고 있는  Matser File Table 을 갖고 있는데요. 그 테이블의 정보를 파싱함으로써 모든 파일의 정보를 빠르게 수집할 수 있습니다. NTFS의 정보들을 파싱하는 다른 포스팅들이 많은데도 불구하고  이 글을 작성하는 이유 는, 실제 구현하면서 부딪히는 문제점들을 알려드리기  위해서 입니다. 저도 검색해서 나온 포스팅을 많이 참고 했는데, 실제로 구현해보니 설명안되어 있는 부분들이 있더라고요. 그 점들은  실제로 구현해보지 않으면 알 수 없는 부분 이니, 그 점들이 다른 포스팅들과의 차이점이 되겠습니다. 다음 글에서는 우선 , NT File system에 대한 내용을 갖고 오겠습니다. 우선 어떤 부분을 파싱할지를 알아야 하니까요 ㅎㅎ. 다음 글에서 보아요.

백준알고리즘 10828번, 스택 풀이

스택의 기본적인 연산 5가지인 push,pop,top,empty,size를 구현하는 문제이다. 별다른 풀이 전략이 필요하지 않다, 그냥 구현만 해내면 그만인 문제이다 스택을 클래스나 구조체로 만들려고 했으나, 굳이 그렇게 할 필요까진 없어 보여 배열과 위치를 갖은 변수하나로 구성하였다. 앞으로 자주 사용된다면 클래스화하여 작성할 예정이다. 참고로,  온라인저지는 컴파일 옵션에 -DONLINE_JUDGE 가 들어가기 때문에 이것을 활용해 예시문을 테스트하는 것을 간편히 만들 수 있다. freopen()을 이용해 인풋과 아웃풋의 스트림을 컴파일 옵션에 따라 바꾼다 . #include <stdio.h> #include <string.h> int main(void) { unsigned int size = 0; int stack[10000] = { 0 }; int n; char cmd[6] = { 0 }; cmd[5] = '\0'; int item; #ifndef ONLINE_JUDGE freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); #endif scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%s", cmd); if (strcmp(cmd, "pop") == 0) { if (size == 0) { printf("-1\n"); continue; } printf("%d\n", stack[size-1]); size--; } else if (strcm...

백준알고리즘 1874번, 스택 수열 풀이

이번 문제에서는 스택을 클래스로 만들어 사용했다. 1~n까지의 수로 이루어진 수열을 스택을 이용해 재현해내는 문제이다. push를 할때는 1부터 순서대로 진행된다.  1~n까지 순서대로 push가 되기 때문에 수열을 재현해내기 불가능한 경우도 나온다. 만약 수열이 일부분이 5, 3 일 경우 5를 pop한 후에 바로 3을 pop하는 것은 불가능하다.(이전 단계에서 4를 pop해 놓지 않은 경우) 일반적으로 고려를 하자면 임의의 k를 pop한 경우 그 다음에 k를 넘어서는 값들이 올 경우 그만큼 push한 후에 pop을 하면 문제가 되지 않지만 k-1보다 작은 값들이 온다면 재현이 불가능한 경우가 된다. 아래 코드의 특이한 점은 변수를 이용해 1부터 n까지 순서대로 push한것이 아니라, 1~n까지의 값을 스택에 넣어 넣고 하나씩 pop하면서 사용했다. 스택 2개를 만들어 사용하는 것을 확인할 수 있을것이다. 전략: m을 pop해야 하는 경우  top이 m보다 작다면 m까지 push한후 pop.                크다면 불가능. #include <stdio.h> #include <string.h> #define MAX_STACK_SIZE 1000000 class Stack { private: unsigned size; int stack[MAX_STACK_SIZE]; public: Stack() { size = 0; memset(stack, 0, sizeof stack); } int Size() { return size; } bool Empty(){ return size == 0; } int Top(){ if (size == 0) return 0; return...

백준알고리즘 9012번, 괄호 풀이

이번문제는 괄호의 유효성을 판단하는 문제이다. 소괄호만을 사용했기 때문에 푸는 방법은 쉬운문제 였으나 스택 수열 문제에서 사용한 스택 클래스를 그대로 사용함으로써 런타임에러가 발생하여 수정하느라 얘를 먹었다. 스택이 Pop() 메소드에서 size가 0인 경우에도 동작하게 만들어 배열의 범위를 벗어나는 접근이 가능하기 때문에 런타임에러가 난것으로 보인다. size가 0인 경우 0을 리턴하도록 수정하니 잘 작동했다.(런타임 에러 메시지를 볼 수 있으면 좋으련만....) 접근방법 : 여는 괄호'(' 인 경우 push를 한다. 닫은 괄호')'이면서 스택이 비어있지 않다면 pop을 한다. (제대로된 괄호라면 닫는 괄호가 나온경우 스택이 비어있을 수 없다.) 모든 괄호를 처리한 후에 스택이 비어있는지 확인한다. 괄호의 짝이 맞다면 무조건 비어있게 된다. #include <stdio.h> #include <string.h> using namespace std; #define MAX_STACK_SIZE 1000 class Stack { private: unsigned int size; int stack[MAX_STACK_SIZE]; public: Stack() { size = 0; memset(stack, 0, sizeof stack); } int Size() { return size; } bool Empty(){ return size == 0; } int Top(){ if (size == 0) return 0; return stack[size-1]; } void Push(int item) { stack[size++] = item; } int Pop() {         if (size == 0) ret...