본문 바로가기

분류 전체보기

Assembly-> C Handray(2) Assembly-> C Handray(1)에서 했던 내용을 약간 응용해서 Codegate 2013 vuln 400 문제를 handray 할텐데요.assembly언어를 C로 handray하는 건 끈기와 인내(?)가 필요한 작업이기 때문에 일부분만 하겠습니다. 이전 글을 읽으시고 핸드레이를 연습하시는 분이라면 이 글은 어셈블리어가 눈에 익숙해지신 분들만 읽어주셨으면 좋겠습니다. 코드가 너무 길어서 일일히 설명해드릴 수가 없고(어차피 노가다이기 때문에 핸드레이 좀 해보신 분들은 이해하실 수 있을겁니다.) Ida의 힘을 빌려 함수와 변수명을 정의하는 과정을 보여드립니다. 일단 이 문제는 이렇게 생겼습니다. 핸드레이에 익숙하신 분은 Ida-pro를 이용해서 코드분석을 빨리 하시는 것도 좋은 방법이지만, 배우는 입.. 더보기
Assembly-> C Handray(1) 시스템해킹, 리버싱을 시작하기에 앞서, 어셈을 C로 바꾸고 C를 어셈으로 바꿀 수 있는 능력은 정말 중요하다고 생각합니다. 리버싱이든 시스템이든 우리는 어셈블리어를 무조건 마주치고 분석해야하는 입장이기 때문입니다.(물론 안드로이드 리버싱을 할 때에는 달빅코드로 되어있어서 어셈블리어와는 약간 다른 개념이지만요.) 문제를 많이 풀어보는 것도 좋은데 전 그전에 C언어로 어떤 코드든 컴파일해서 그걸 디버거로 역분석하여 핸드레이로 다시 복원하는 연습을 하셨으면 좋겠다고 생각합니다. 짧게는 한달, 많게는 두달까지요. 이 기준은 여러분이 적당하다고 느낄때까지 입니다. 복원하는 연습을 꾸준히 하다보면 어셈블리어코드가 자연스레 눈에 들어오는데, 그정도면 성공입니다. 예를 들어서, 간단한 코드가 있는데 gdb로 열어보면 .. 더보기
5. *p와 p[]의 차이. *p와 p[]의 차이를 설명하기에 앞서 간단한 코드를 보여드리겠습니다. 1번은 배열을 이용해서 각각 *(a + 2), a[2], 2[a]를 출력하고 있고 2번은 char형 포인터에서 b[2]에 해당하는 값을 출력하는 겁니다. 각각 어떤 값이 출력될까요? 1번 여러분이 아시는 a[2]는 당연히 3이 출력되겠죠. 그렇다면 2[a]와 *(a + 2)는 어떤 값이 출력이 될까요? 똑같이 3, 3이 출력이 됩니다. 여기서 눈치가 조금 빠르신분은 대충 아셨겠지만 a[2]는 배열이 아닙니다. 포인터 변수를 배열처럼 사용했을 뿐. a[2]의 의미는 a에서 2만큼 더 떨어진 곳의 값을 지칭합니다. 그래서 *(a + 2) == a[2]는 같은 표현이죠. 그렇다면 2[a]는 무슨 뜻일까요. C언어에서 []는 연산자를 나타냅.. 더보기
[OpenGL] 그래픽스 자유곡선 그리기 #include #include #include #define TRUE 1 #define FALSE 0 GLint TopLeftX, TopLeftY, BottomRightX, BottomRightY; //마우스의 좌표값을 저장하는 변수 GLfloat R = 0.0, G = 0.0, B = 0.0; //선의 색상 정할 때 이용되는 변수 GLboolean Line = TRUE; //TRUE로 설정을 해서 처음 실행하면 직선을 그린다. bool identify = TRUE; //마우스를 누르고있으면 false, 안누르면 true. false일 때 자유곡선을 그린다. bool click = TRUE; // 화면 초기화 안되게 막아주는 변수 void MyDisplay() { if(click == TRUE) // .. 더보기
초기화되지 않은 변수에 쓰레기값이 들어있는 이유 동아리방에서 이런 얘기가 오고가서 글을 올려봅니다. printf로 초기화되지 않은 a의 값을 출력하는데 "쓰레기값이 왜 들어있는거에요?" 이건 printf 이전에 메모리할당으로 넘어갑니다. 변수를 선언하기 이전의 메모리 모습입니다. 여기엔 이상한 값들이 들어가있어요. int형 a 변수를 선언했을 때의 메모리 모습입니다. 처음 a 변수를 선언했을 시, a의 앞으로 4바이트 뒤로 200바이트정도에 모두 cc값을 넣어서 스택을 할당합니다. 이 cc가 흔히 말하는 쓰레기값이죠. 보는 바와 같이 a 변수에 4를 초기화시켜서 a엔 4, 그 위로는 b의 값인 5가 들어갑니다. 나머지 cc cc cc cc, cc cc cc cc, cc cc cc cc 는 초기화되지 않은 변수 c, d, e로 들어가게 되는거죠. 결론은.. 더보기
4. sha == sha[0] == &sha[0][0] 3. 배열포인터에서 int sha[3][2]; int (*psha)[2]; psha = sha일 때 배열 sha는 배열의 첫번째 주소를 가리킨다고 했었습니다. 그렇다면 sha == sha[0] == &sha[0][0] 이건 맞는 문장일까요? 맞는 문장이네요. 하지만 주소만 보고 정말 저 문장이 똑같다고 할 수 있을까요. sha는 전체 배열을 뜻하고 sha[0]은 0행 전체를, sha[0][0]은 [0][0] 하나를 가리키고 있습니다. 그래서 sha는 3 x 2 x 4 인 24가 나오고 sha[0]은 2 x 4 sha[0][0]은 4가 나옵니다. 이로써 sha == sha[0] == &sha[0][0] 는 가리키는 주소만 같을 뿐 완전히 다르다는 걸 알게 됬습니다. 더보기
3. 배열포인터, 이젠 아무대나 *쓰지말자! *의 두가지 의미를 설명했을 때, 제일 중요했던 건 1. 초기값을 지정해줄 때의 *는 번지를 가르키는 걸 뜻했고 2. 수식에서의 *는 포인터변수가 가르키는 주소의 값을 리턴한다고 했습니다. 이 두가지는 포인터를 하시면서 반드시 기억해주세요. 오늘은 배열포인터에 대해 글을 쓸게요. 우선, 배열이 뭘까요. 여러분도 다 아시듯 array[3] = {1, 2, 3} 이런식으로 변수 여러개를 편리하게 지정할 수 있죠. 그렇다면 배열의 포인터는? 배열 포인터변수에 배열의 주소값을 넣게 될 경우, 배열의 첫번째 번지를 가르키게 됩니다. array[3]이라면 array[0]을 가르킬 것이고 array[2][3]이라면 array[0][0]을 가르키겠죠? 이런식으로 표현할 수 있겠습니다. (주소크기가 1씩 증가하는건 그냥.. 더보기
2. 포인터가 4바이트인 이유 '포인터는 주소를 가리키기만 하면 되기 때문에 4바이트 이상 필요하지 않아요.' 사람들에게 물어보니 이런 답을 많이 들었습니다. 왜 하필 4바이트일까요. 전 이렇게 생각합니다. 32비트 CPU의 주소값은 4바이트로 표현됩니다. (8비트당 1바이트이기 때문에 ) 예를들어 10진수는 7141840, 11008720, 17038120, 16645524 16진수는 0x103dc90, 0x8047c24, 0x104fa78 이런식이죠.. 만약, 64비트 CPU의 PC(Program counter)가 32비트를 쓰고 있다면 포인터의 크기는 4바이트가 될 것이고, 64비트를 쓰고 있다면 포인터의 크기는 8바이트가 됩니다. (여기서 말하는 PC란 CPU 내부에 있는 레지스터 중의 하나를 말합니다. PC는 다음에 실행될 .. 더보기
1. *의 두가지 의미 포인터를 시작하기 전에 *의 의미를 알아두면 포인터를 더 쉽게 이해할 수 있습니다. 예를 들어 여기서 몇번 항목이 에러가 날까요? 1번 int* pa = &a포인터변수 pa는 초기값으로 a의 주소를 받았습니다. *pa = 10; 그리고 pa가 가르키는 곳(a)에 10을 넣어서 printf로 a를 출력합니다. 그렇다면 출력되는 값은 5가 아닌 10이 출력됩니다. 2번 int* pb; 포인터변수 pb에는 초기값을 지정해주지 않아서 포인터변수 pb가 가르키고 있는건 쓰레기값입니다. pb = &b; 포인터변수 pb에 b의 주소를 넣었습니다. *pb = 1000; pb가 가르키고 있는 곳(b)에 1000을 넣어서 printf로 b와 포인트변수 pb가 가르키고 있는 곳을 출력했습니다. 출력되는 값은 b와 *pb 모.. 더보기