2009년 12월 20일 일요일

Pranav Mistry: SixthSense 기술의 놀라운 잠재력 [TED]























@TEDindia
Pranav Mistry / MIT MediaLab

8년 전에 볼마우스를 분해해서 제스쳐인식 장치를 만들기 시작한 Pranav는 실제세계와 디지털세계를 연결에 필요했던 디스플레이 장치들을 없애고, seamless 하게 만드는 sixth sense 장치를 만들기에 이르른다.
3D로 사람의 동작을 인식해서 디지털화하는 모션센서가 새로운 기술은 아니지만, 종이에 장치를 꽂아서 종이 자체를 디스플레이로 사용하게되는 장면은 정말 놀랍다!

stylus, touchscreen 등의 디스플레이가 막 상용화되고있는 이 시점에서 벌써 다음 세대의 디스플레이가 준비되고 있다.


2009년 12월 18일 금요일

카네기 인간관계론

"경청하라"
"미소짓는 얼굴로 대하라"
"겸손하라"
"자주 칭찬하라"
"이름을 기억하고 먼저 인사하라"

2009년 12월 12일 토요일

Branding “App”: Why Zune Should Just Let Apple Have It

Branding “App”: Why Zune Should Just Let Apple Have It

Posted by Allison Mooney on August 27, 2009 05:32 PM

There’s been a lot of talk about branded apps recently, but what about the branding of the word ‘app’?

App is a strong and powerful term. A noun of action from the Latin ‘applicare,’ it connotes getting stuff done, as in, applying something or oneself. Now it is synonymous with those little downloadable widgets on an iPhone.

It almost feels like Steve Jobs invented the term: Apple has the “App Store,” the catch-phrase “There’s an app for that” — heck, it’s even part of their name. But the Engadget report that Microsoft’s Zune HD will be using the word “Apps” in their “marketplace” raises the question: Can they do that?

Well, yes, of course they can. The word “application” has been around — in a compute sense. The definition, according to Wikipedia:

In computer science, an application is a computer program designed to help people perform a certain type of work. An application thus differs from an operating system (which runs a computer), a utility (which performs maintenance or general-purpose chores), and a programming language (with which computer programs are created). Depending on the work for which it was designed, an application can manipulate text, numbers, graphics, or a combination of these elements.

According to Etymonline, the shorthand term ‘app’ was “attested” in 1992.  (I’m sure there’s a William Safire out there who can tell us the full etymology. Consider this an invitation; comments are open below.) Indeed, the word is securely in the public domain. There are Facebook Apps, Google Apps, Twitter Apps…  Following the popularity of Apple’s App Store, Palm announced the App Catalog, and RIM launched its application store BlackBerry App World.

Still, I can’t help but think this is all great branding for Apple. Every time I hear the word “app,” my brain auto-completes the “le.” So the news that Zune was using the word—prominently on the interface of their new Zune HD—gave me pause. For a company that has been trying... and trying... to position itself as the anti-Apple, it seemed like a disconnect. If Zune does indeed start an application platform, as has been speculated, I’d be curious to see what they choose to call it— if they brand it at all. By way of example, you’ll notice that Android steers away from the word in their marketing copy (it’s the “Marketplace”), as does Nokia’s Ovi, which refers predominantly to “services.”

What do you think? Is the word “app” so fully appropriated by Apple that it has become a branded term? Frankly, I am sick to death of hearing about “apps” (of course this could have to do with the fact that I work in one of the most tech and media saturated cities—at a mobile agency…). But I would love to see Zune come up with something fresh and new that they can really own. What’s after the app? Or what’s the Apple alternative? Tell me, Bill Gates! Perhaps you are too busy saving the reputation of “PC.” Or “Zune,” for that matter.


http://www.brandchannel.com/home/post/2009/08/27/Branding-e2809cAppe2809d-Why-Zune-Should-Just-Let-Apple-Have-It.aspx

2009년 11월 22일 일요일

[시민학교] 신영복, “가슴으로 생각하고, 발로 변화하라”

출처: 우공이산 http://asadal.bloter.net/6735


강연요약을 읽은것에 불과하지만,

가슴이 뛴다.


온화하고 평화로운 길이었다. 숲으로 가는 길. 길은 사람을 향해 나 있었고, 사람과 손잡고 걸어가는 길이었다. 나 홀로 앞만 보고 가선 숲으로 갈 수 없다. 길가의 들꽃과 풀을 만지고 교감하고, 손 맞잡은 사람끼리 웃고 얘기하고, 주변 풍경과 공기를 음미하며 천천히 나아가야 비로소 숲에 다다를 수 있다. 그랬다. 숲으로 가는 길은.

함께하는 시민학교가 열린 특강 ‘개념있는 시민학교’를 마련했다. 신영복 성공회대 석좌교수가 길을 텄다. 마포 성산동 시민공간 나루 안 ‘성미산 마을극장’이 일찌감치 꽉 찼다. 쫑긋 세운 귀, 반짝이는 눈, 두근대는 심장으로 가득 찼다. 더러는 일찌감치 수첩과 볼펜을 꺼내들었고, 더러는 부러 챙겨온 듯한 몇 권의 책을 만지작거렸다.

강의는 2시간으로 예고됐지만, 시간을 맞추는 게 중요한 일은 아니었다. 시계를 들여다보려는 이를 찾기는 어려웠다. 그깟 넘어선 시간들이 숲으로 가는 먼 여정을 방해할 순 없었으니까.

신영복 교수가 이끄는 ‘숲으로 가는 길’은 사람의 이치를 깨닫는 길이었다. 냉혹한 판단과 저울질로 굴러가는 이성의 ‘머리’, 대상이 아닌 사람을 바라보고 느끼는 ‘가슴’, 깨닫고 느낀 바를 실천으로 옮기는 ‘발’에 관한 우화였다. 근대 이성의 오만함에서 벗어나 ‘마이너리티’들의 자유분방한 상상과 혁신으로 세상을 바꿔나가자는 호소였다. 나홀로 크는 나무가 아니라 주변을 아우르고 공감하는 숲을 완성하자는 자기 다짐이기도 했다. “시속 100km로 앞으로 달려가는 사람은 100m 앞 코스모스도 제대로 보지 못하는 법”이니까.

더불어 함께하니 길은 저절로 열렸다.

<강연 요약>

독일 철학자 칼 야스퍼스는 사회를 변화시키는 세 주체로 국가, 교육, 대학을 꼽았다. 그의 저서 <대학의 이념>은 국가 권력기관으로부터 대학의 독립성을 강하게 주장한다. 오늘날은 야스퍼스가 상정했던 대학은 없다고 생각한다. 대학은 기업으로부터 훨씬 많은 영향을 받고 있다. 넓은 의미에서 대학은 그 사회에서 필요한 전문인력도 공급해야 한다. 그러나 자본과 국가로부터 독립된 공간으로서의 대학은 현재 이야기할 수 없다.

저는 학교 체질이다. 계속 학교에서만 있었다. 도중에 겪었던 20년 감옥 생활도 학교로 쳐준다면. (일동 웃음) 아버지가 선생님이라 저는 학교 사택에서 태어났고, 어릴 적부터 학교 사택에서 교실로 내려가 놀았다. 그러다 학교를 졸업하고 27살에 교도소로 들어갔다. 그리고 1988년 출소한 뒤 89년 1학기부터 또 학교로 들어갔다. 내 인생을 돌아보니 20년 주기가 있더라. 감옥 이전 20년, 감옥 20년, 감옥 이후 20년이다. 지금도 학교에 잡혀 있다.

상아탑에 있다보면 오늘날 복잡한 사회적 쟁점에 대해 열띠게 토론할 입장이 안 된다. 그러나 좀 거리를 두고 근본적 사고를 하는 사람도 사회에 필요하지 싶다. 여러분과 그런 점을 성찰하는 자리를 가지려 한다.

감옥에 있을 때 ‘주역’을 많이 읽었다. 주역에 ‘석과’(碩果)란 말이 나온다. ‘씨 과실’이다. 오늘은 씨 과실이 숲으로 가는 길에 대해 얘기하려 한다. 미야자키 하야오의 ‘이웃집 토토로’를 보면 “씨앗은 숲으로 가는 여행이다”라는 구절도 나온다. 마지막 석과가 언제 떨어질 지 모르는 상황, 남은 하나마저 뺏길 지 모르는 굉장히 어려운 상황을 뜻한다. ‘효4′에 보면 ‘석과불식’(碩果不食)이란 말이 나온다. 씨 과실은 결코 먹지 않는다. 먹지 않고 씨를 받아 땅에 묻는다. 이듬해 새싹으로 돋아난다.

이 씨가 숲으로 가려면 어떻게 해야 하나. 첫 번째는 잎사귀를 다 떨어뜨려야 한다. ‘엽낙’(葉落)이다. 잎사귀가 다 떨어지면 몸체를 드러내야 한다. 그게 ‘체로’(体露)다. 잎사귀를 떨어뜨리는 건, 거품을 걷어내고 환상을 청산한다는 걸 상징한다. 추경예산 조기집행하고 4대강 사업 추진하면 경제 위기가 극복될 거라는 환상같은. 그런 환상을 걷어내면 뼈대가 선명히 드러낸다. 한 사회, 한 개인의 뼈대, 가장 근본적인 구조가 드러난다. 정치적 자주권은 있는지, 문화적 자존심은 있는지, 식량과 에너지를 어느 정도 자급할 수 있는 경제 구조가 있는지. 소위 말하는 ‘신자유주의’가 굉장히 부당하고 지속가능하지 않다는 게 속속 드러나고 있다. 개인도 마찬가지다. 옷과 패션을 벗으면 알몸이 된다. 자기가 추구하는 가치가 무엇인지, 서 있는 자리가 어디인지를 분명히 하는 게 첫 번째다.

다음은 ‘분본’(賁本). 뿌리를 거름해야 한다. 잎사귀들이 뿌리를 따뜻하게 덮고 거름하는 상태다. 한 사회의 ‘본’이 무엇인가. 여기서 정치적 입장이 나뉜다. ‘본’은 인간이다. 한 사회의 잠재적 가능성을 극대화하는 게 바로 ‘정’(政), 정치다. 정치는 권력을 쟁취하고 지키는 게 아니다. 한 사회의 잠재적 가능성을 최대화하는 게 정치다. 지금은 사람을 따뜻하게 키우는 게 아니라 반대다. 사람을 거름으로 쓴다. 끔찍하다.

절망적 상황에 직면했을 때 크게 두 가지 방식의 대응 행태가 있다. 하나는 실사구시다. 사실에 다가가서 참됨을 구하는 것이다. 이 점에서 우리 사회가 합의하고 있다. 이건 진리(眞理)가 아니라 물리(物理)다. 사실에 다가가 여러 팩트들의 상호관계를 조정하고 순위를 매기고, 구조조정하는 것이다. 사회의 장애를 둘러싼 많은 팩트들을 조정하는 게 실사구시다. 이건 물리적 영역이다.

그런데 만약 경제가 애로에 봉착하면 어떻게 조정할 것인가. 지금까지는 구조조정, 노동유연성 식으로 사람을 조정했다. 다른 하나는 경제란 개념 자체를 재구성하는 것이다. 경제가 무엇인가, 왜 경제를 살려야 하는가 하는 근본 개념을 재구성하는 것이다. 그게 ‘진리’다. 우리가 익숙한 건 물리적 대응이고, 거기에 합의하는 것은 아닐까. 단기적으로는 그것도 필요하다. 그러나 근본 방향과 목표에 다가가기 위해서는 진리 문제에 반드시 부딪힌다. 인간의 근본 문제, 야스퍼스가 지적했듯이 인간에 대한 냉정한 이해와 직시가 필요하다.

문제는 ‘머리’다

오늘은 인간에 대한 얘기를 하고 싶다. 머리, 가슴, 발 세 부분으로 말씀드리겠다. 먼저 머리 부분을 가장 문제삼고 싶다. 데카르트 이후 인간은 우리 생각이 이성적이고 합리적이라고 선언했다. 근대 사회의 특징이 이성이다. 중세 암흑기에 비추면 데카르트 선언은 굉장히 혁명적이지만, 그 이성이 정말 합리적인가의 문제가 여지없이 해체되는 게 오늘날 지적 상황이다.

중세는 중세의 문맥이 있다. 예컨대 마녀가 있었다. 시대가 마녀를 인정했고, 심지어 처형된 마녀조차 자기가 마녀란 걸 자백하고 처형당한 경우도 상당하다. 지금 보면 어리석은 문맥이라고 생각하겠지만, 시각을 달리해보자. 우리는 문맥에 갇혀 있지 않은가. 냉정히 보자. 뿌리에 해당하는 인간 이해에 있어 갇혀 있지 않은가. 나는 갇혀 있다고 본다.

두 사람이 있다 치자. 한 사람이 다른 사람을 잘 이해하는 방법은 무엇인가. 대개는 그 사람의 정보를 면밀히 분석하면 이해할 수 있다고 생각한다. 이런 관점을 우리 대부분은 갖고 있다. 사실은 A가 B를 잘 이해하려면 B가 A를 잘 알아야 한다. ‘관계’가 있어야 한다. 관계 없이도 인식이 가능하다는 것은 이성의 오만의 극치다. 둘 사이에 관계가 있으면 반드시 양방향 변화가 이뤄진다. 변화 없이 일방적인 인식이 누적되고, 그 누적된 인식을 일방적으로 수용할 수 있다는 것은 이성의 오만이다.

인식을 예전에는 ‘구도’라고 불렀다. 도에 이르는 데는 고행이 수반된다. 고행을 통해 주체가 변화되는 걸 뜻했다. 그러지 않으면 도에 이르지 못한다. 지금은 전혀 그렇지 않다. 자기가 반짝이는 이성만 있으면 상대방을 대상화하고 타자화한다. 우리가 갇힌 근대 문명은 이성의 주체성에 철저히 매몰돼 있는 사고다. 특히 인간 이해에 있어선 말할 필요도 없다.

한국 사회를 지배하는 문맥은 대단히 많다. 전쟁 문맥도 많다. 아직 한국은 전쟁중이다. 우리나라가 소통이 안 되는 바탕에는 전쟁 문맥이 깔려 있다. 전쟁은 소통 문맥이 아니다. 찬반 양론으로 갈리어 어떻게 소통이 되나. 자기가 변화하지 않으면 소통이 안 된다. 당신이 얘기해보라, 그래 그 얘기 인정하겠다, 하는 게 무슨 소통인가.

우리가 갇혀 있는 문맥은 분석하고 대상화하는 것이다. 상품 문맥도 있다. ‘쌀 한 가마=구두 한 켤레’란 예를 들어보자. 쌀이 상품이라면, 상품은 팔기 위한 것이다. 상품은 등가물로서 자기를 표현해야 한다. 상품이 아니면 그냥 먹으면 된다. 사람을 쌀 자리에 놓았을 때 이 사람이 구두 한 켤레와 같다고 말한다면 그 사람은 굉장히 섭섭해할 거다. 그런데 그 사람 연봉이 10억원이라고 하면 섭섭해하지 않는다. 구두 한 켤레든, 연봉 10억원이든 등가물이긴 마찬가지다. 품성이나 매력과 상관없이 인간이 등가물로 표현된다. 다른 말로 ‘등신’이라고 불렀다.

나도 등신 노릇 많이 했다. 교도소 목공소에서 일할 때다. 나는 기술이 없으니 다른 사람이 톱질할 때 안 흔들리게 나무를 밟고 서 있으라고 하더라. 나도 명색이 대학교수 하다가 감옥 갔는데, 무게와 등가물이 됐다. (일동 웃음).

우리 아파트에 유명한 변호사와 별로 미인이 아닌 부인 부부가 있었다. 흔히 말해 어울리지 않는 부부였다. 모든 아파트 사람들이 의아한 시선으로 이들을 바라봤다. 그리고 아파트 사람들이 내린 결론이, 그 부인 집이 부자일 거라고들 했다. (일동 웃음). 루저 파문도 마찬가지다. 자기가 보는 관점에서 키가 작은 남자는 부족하다고 말하는 게 등가물로 바라보는 거다.

근대사회는 자본주의 사회다. 자본은 자기 가치를 증식하는 것이다. 내 돈을 교통비나 밥값으로 쓰면 가치 증식이 아니다. 물건을 사거나 투자하는 게 자본이다. 개인이든, 기업이나 단체든, 국가든 자기 가치를 키우는 게 근대사회에서 일관되게 나타나는 현상이다. 다른 사람을 대상화하고 분석한다.

내가 감옥 초년에 깨달은 게 있다. 내가 근대적 사고에 충실한 근대인이구나. 죄수들을 바라볼 때 저 사람이 결손가정인지, 지위는 어떤지 계속 분석하고 대상화했다. 그런 기간 동안은 당연히 왕따였다. (일동 웃음)

‘가슴’으로 가는 긴 여정

그래도 나는 합리적이고 이성적인 사람이라고 생각했다. 세월이 지나면서 많은 사람을 만나고 얘기하고 듣다보니 납득이 가더라. 20년간 한 곳에 갇혀 있었지만 많은 사람을 만났다. 나도 같은 부모 밑에서 태어나 저렇게 어려운 상황에서 생활했다면 저 사람 죄명을 달고 여기 서 있을 지도 모르겠다는 생각을 했다.

머리가 이성적인 영역이라면, 가슴은 공감의 영역이다. 머리로부터 가슴으로 가는 것이 중요하다. 우리가 생각하라고 할 때 ‘전두엽에 손을 얹고 조용히 생각하라’고 말하지는 않는다. ‘가슴에 손을 얹고 생각하라’고 한다. 머리가 아니라 가슴이 생각하는 것이다.

해 저문데도 아직 돌아오지 않는 어머니를 생각한 적이 있지 않나. 생각은 그런 거다. 이성하고 상관 없다. 생각은 그 대상을 자기 세계로 받아들이는 것이다. 자기가 참여한다는 뜻도 된다. 강도에게 칼을 맞아 쓰러져 있는 유태인을 많은 사람들이 그냥 지나갔는데 사마리아인이 부축해 여관으로 데려가 치료하고 보호했다. 그건 유태인을 자기 세계로 받아들이고 생각한 것이다. 세계는 가슴으로 조립하는 것이다.

진리는 어떤가. 불변의 진리? 이것이 근대사회의 문맥이다. 초역사적 불변의 진리는 없다. 진리는 조직하는 것이다. 역사는 역사가가 조직하는 것이다. 수많은 지난 사건들 가운데 역사가가 일부를 선택해 조직하는 것이다. 사마천 ‘사기’를 읽는 것은 중국 근대사를 읽는 게 아니라 사마천을 읽는 것이다.

생각. 대단히 중요하다. 가슴이 생각하는 게 맞다. 멀리 돌아오지 않는 친구를 생각하는 건 자기 세계로 받아들이는 것이다. 자기와 관계 없는 걸 대상화하고 분석할 수 있다는 냉혹한 근대 이성을 넘어 가슴까지 오는 것, 사람이 일생동안 하는 여행 중 가장 먼 여행이다.

공감 단계에 올 때까지 저도 아픈 기억들이 많다. 그래서 충분히 그 사람들을 이해하고 공감하고 공존할 수 있다는 단계에 와 있다는 걸 스스로 굉장히 흐뭇해했다. 거대한 여행을 끝내고 무척 발전했다고 생각했는데 그게 아니었다. 공감한다는 것, 애정을 가지고 봉사한다는 것, 대가 없이 진정으로 다른 사람을 동정하는 것. 미덕이긴 하지만 다시 한 번 생각해봐야 한다. 동정받는 입장에 있는 사람은 동정받는 순간 자기가 동정의 대상이라는 아픈 자각을 다시한번 하게 된다. 돕는다는 건 그래서 우산을 들어주는 게 아니라 함께 비를 맞아주는 것이다.

집을 그리는 노인 목수 얘기를 책에도 썼고 여러 번 얘기했다. 그 노인 목수는 집을 주춧돌부터 기둥, 지붕 순서로 그렸다. 그 옆에 앉아서 나는 굉장한 충격을 받았다. 일하는 사람들은 집 짓는 순서와 그림 그리는 순서가 같구나. 선생 아들로 태어나 주욱 학교에서 생활한 나는 지붕부터 그리고 있구나.

변화는 ‘발’에서 비롯된다

‘대의’란 이름을 가진 재소자가 있었다. 30대인데도 절도 전과가 서너 개는 있었다. 어느 날 내가 딱히 여겨 물었다. ‘네 이름은 아버지가 지었나?’ 그러니 ‘난 아버지가 없는 고아다’라고 대답하더라. 돌이 채 안 될 때 버려졌는데, 발견된 곳이 광주 대의파출소 바로 옆이라 이름이 대의가 됐다고 했다. 또 충격받았다. 나는 문자가 주는 고정관념에 사로잡혀 있구나. 이걸 바꾸려 했다. 가슴에서 발까지 가야 한다.

발은 변화를 상징한다. 소통도 변화가 전제되지 않으면 소통이 아니라고 말했다. 변화를 위한 노력들을 참 많이 한다. 포스트모더니즘의 주요 주제가 해체와 변화였다. 나는 사회변혁기에는 감옥에 있었지만, 자기 변혁에는 성공했다고 생각했다. 머리는 사람을 ‘개인’이라 생각하지만 발로 오면 사람은 ‘관계’가 된다. 관계를 형성함으로써 개인이 안정화된다. 관계속에 서야 한다. 나도 처음엔 감옥에서 왕따였는데, 관계 단계로 오니 감옥이 정말 든든해졌다.

징역 말년에는 상당히 편했다. 원래는 내내 요시찰이었다. 대공분실에서 몇 번 와서 추가 조서 받은 적도 있으니까. 다른 재소자에게 좋지 않은 영향을 끼치지 않을까 생각했는지 불시에 방 점검도 많이 당했다. 그래서 내 방에는 책이 한 권도 없었다. 그럼에도 나는 적발되면 당장 압수될 수준의 책 40여권을 이동문고로 돌리고 있었다. 다른 재소자들과 손발이 잘 맞았으니까. 절도, 쓸이범 친구들이 얼마나 잘 하는데. (일동 웃음) 그게 관계였다.

그런 관계가 대단히 인간적이기도 하다. 이념적 관계도 아니다. 서로의 치부를 다 공유하는 관계임에도 따뜻하다. 아프다고 하면 몰래 숨겨둔 약을 보내주기도 하고, 추운 겨울에는 뜨게질한 양말도 나눈다. 생각해보면 그런 관계 덕분에 감옥을 견디지 않았을까 생각한다.

출소 직후만 해도 나는 개인 개조나 변화를 개인적인 관점에서 바라보고 있었다. 변화도 사람과 더불어 관계맺는 속에서 이뤄질 수 있다. 관계가 대단히 중요하다.

최근 알랭 바디우 책을 읽었다. 탈근대의 철학적 담론들이 다 해체인데, 그럼 주체는 어떻게 구성되는가 하는 새로운 문제제기를 한다. 그러면서 진리란 기존 진리체계의 바깥에서 사건으로 돌출하는 것이라고 바디우는 말한다. 천동설이 진리체계였을 때 지동설은 진리체계 외부에서 사건으로 돌출했다. 후사건적 실천이 주체를 형성한다. 대단히 중요하다.

오늘은 여러분과 공유하고픈 게 ‘변화’다. 생각은 실제로 변화해야 한다. 이 변화가 가능하기 위해선 머리부터 가슴, 발까지 길고 먼 여행을 해야 하겠지만 가장 중요한 건 외부에 대한 사고다. 갇혀 있는 진리체계의 바깥에 사건으로 돌출하는 것. 쇤베르크 음악도 마찬가지다. 음악적 구성이나 화음이 원래 아인슈타인의 수학 논리처럼 복잡하다. 그걸 7음계로 나눴다. 그걸로는 미분이 안 되니 중간에 반음을 넣었다. 그러다가 12음계로 바꿨다. 쇤베르크가 고전 음악의 진리체계를 무너뜨리고 음악을 진리체계 바깥에서 돌출했다.

파리꼬뮌은 또 어떤가. 1871년에 70일동안 일어난 짧은 사건이다. 베르사이유 궁전에 버려진 노동자와 농민이 자기들만의 정권을 꾸렸다. 파리꼬뮌이란 사건이 돌출하기 이전까지는 노동자나 서민의 정치역량에 대해 누구도 생각하지 않았다. 그 이후 정치 권력의 한 축으로 당당히 차지했다. 진리는 그렇게 찾아온다.

주변부는 변화의 가능성이 훨씬 높다. 중심부는 완강한 구조 탓에 새로운 사고가 나오기 어렵다. 변화는 바깥에서 나온다. 마이너리티가 돼야 한다.

마이너리티는 양적 관점이 아니다. 양적으로는 마이너리티가 아니다. 중심부가 갖는 영향력은 크다. 조중동, 국가, 제도, 법 등 강력한 기제가 있다. 역사적으로 지금이 가장 강력한 기제를 발산하지 않나 생각한다. 과거엔 물리적 기제에 의존했다면 지금은 상대방 동의에 기초했다는 헤게모니 또는 정서 자체를 포섭한 거대한 구조다. 양적으론 소수이지만 파워면에선 반대다. 문제는 중심부가 행사하는 파워가 어디서부터 나오느냐이다. 바로 주변부에서 온다. 피지배자라는 주변부는 다수이고, 지배하는 중심부는 소수다. 다수는 힘이기도 하고 정의이기도 하다.

교도소는 우리 사회의 철저한 마이너리티다. 그 언덕에 기대어 저도 변화를 고민할 수 있었다. 마이너리티의 창조성에 주목해야 한다. 연암 박지원은 우리나라 최고의 사상가이자 문장가다. 우리나라 최고의 저서가 ‘열하일기’다. 연암은 16살에 처음 글공부를 했다. 노론 집안이었지만 가난했기에 배움이 늦었다. 장가든 이후 처삼촌이 글을 가르쳤다. 열하일기를 읽어보라. 문장이 아주 뛰어나고 참신하다.

다산은 또 어떤가. 그런 시대에 그런 사고를 했다는 게 우리의 위로이기도 하고 자존심이기도 하지만, 당대의 다산은 어떤가. 다산초당에 앉아 있을 당시 다산은 철저한 마이너리티였다. 그래서 여유당전서를 쓸 수 있었다. 마이너리티가 되자는 실천적 사고를 한 것이 변화의 핵심이다.

배워야 한다. 촛불집회때 보면 사회단체 대표들이 깃발을 들고 주욱 나타난다. 촛불이 이뤄놓은 일정한 성과를 자기 조직을 강화하는 데 고민하는 모습을 봤다. 대단히 안타까웠다. 그 세대, 그 사고들은 어딘가 서버에 접속해야 한다. 웹1.0 세대다. 촛불은 어디에도 접속하지 않는다. 하나하나가 독립된 서버다. 공간공동체란 옛날 관점으로 돌아가선 안 된다. 사람이 새로운 사고를 하는 건 굉장히 어렵다.

오늘날 변화된 정서나 상황을 과거의 틀, 공간공동체란 문맥이 아닌 다른 문맥으로 키워낼 수 있을까. 그걸 사회운동하는 분들이 고민해야 한다. 새로운 전형을 고민해야 한다. 열심히 뛰어 양적으로 많은 모임을 만들어낸다고 해서 잘 되는 게 아니다.

감옥에서 네루와 간디를 함께 읽었다. 네루가 쓴 ‘인도의 발견’이란 책이 있다. 결국 인도를 발견한 건 네루가 아니라 간디다. 네루는 근대사회의 인식을 복사해 인도에 인식하려 했다. 간디는 가난하고, 카스트란 사회적 계급구조에 억눌려 있고, 종교란 환상에 젖어 있는 나약한 인도 국민들로부터 식민지 독립을 위한 창조적 동력을 어디서 끌어내야 할 지 꿰뚫어봤다. 그건 ‘비폭력 무저항’이었다. 인도의 현실과 정서에 맞는 새로운 항쟁의 전형을 만들어냈다.

나는 간디를 종교적 성자가 아닌, 뛰어난 정치전략가라 생각한다. 바이샤 출신의 마이너리티 간디가 가진 자유로움이었다. 결정적인 건, 콤플렉스가 없어야 한다. 중심부를 향한 허망한 콤플렉스를 가져선 안 된다. 콤플렉스는 대단히 완고하다. 한 개인의 판단에 최후까지 작용하는 건 자기도 모르는 콤플렉스다. 한 사회 문화구조 속에 콤플렉스가 굳어 있다면 그 사회는 합리적 가치를 설정할 수 있는 사회가 아니다.

더불어 공감하고 나누는 ‘숲’으로 가자

숲으로 가자. 나무의 완성은 숲이다. 숲에는 서로 공유하는 게 있다. 서로 알고 있는 걸 확인하는 것이다. 위로이기도 하고, 약속이기도 하다. ‘젊은 베르테르의 기쁨’이란 책을 본 적 있나. 처음 책 제목을 들었을 때 ‘젊은 베르테르의 고뇌’가 아니라 ‘기쁨’이라니, 한참을 찾았다. 책을 샀더니 쇼펜하우어가 쓴 책이었다. ‘모든 사랑은 아픔’이라는 ‘젊은 베르테르의 고뇌’를 읽은 독자들이 사랑은 이렇게 아픈 것이구나 하고 깨달음을 갖게 된다. 그 아픔이 눈물젖은 아픔이라도 결국 깨달음에 이르고 철학이 되고 지식이 된다. 그래서 고뇌가 아니라 기쁜 것이다, 란 인식이다.

숲은 기쁜 곳이다. 에피쿠로스가 말했다. 우정은 음모다. 주변부를 공유하는 게 우정이다. 다른 사람에게 비난의 대상이 되고 상식에 벗어나는 행동에 대해 질타당할 때 그 사람 옆에 가서 공유하는 것, 비난을 음모하는 게 우정이다. 숲은 우정과 음모를 키우는 진지가 되고, 사회변화 과정에서는 뛰어나가는 거점이 되기도 한다. 자유로운 숲들을 도처에 만들어내는 게 필요하다. 숲의 개념마저도 새로운 개념으로, 개념있는 시민학교가 고민해야 한다.

석과에서 숲으로 가는 길이 쉽지 않다. 인생은 공부라고 생각해야 한다. 먼 여행이라고 생각하면 공부가 지겹지 않다. 시민학교도 공부하는 장소다. 약속하고 격려하는 장소다. 교도소에서 단기수들은 굉장히 괴로워한다. 하루하루가 지나가는 걸 매일 체크한다. 하루하루를 버리는 것이다. 목표와 관계없이 과정 자체에 대해 자부심과 가치를 느껴야 한다. 그게 중요하다. 먼길을 가는 사람에겐 ‘고진감래’라는 논리는 통하지 않는다. 현실 자체가 즐겁고, 우정이 있고, 음모가 있고, 사람을 만나야 한다.

사람만이 직선으로 고속도로를 달린다. 강아지는 그렇지 않다. 길 곳곳의 특질들을 파악하고 흔적을 남긴다. 시속 100km로 지나가는 사람들은 100m 앞의 코스모스도 보지 못한다. 자기가 하는 일 자체가 보람있고 아름다운 공부여야 한다. 안 그러면 먼 길을 절대 못 간다.

자본주의 사회의 물신적 욕망 구조는 만들어진 욕망 구조다. 자기 주체성을 갖고 자부심을 갖는 게 굉장히 중요하다. 먼 길을 견디는 방법은 우선 길 자체로부터 동력을 이끌어낼 수 있는 의미를 찾아야 하고, 자기가 하는 일에 자부심을 가져야 한다. 함께가면 좋다. 함께한다는 데서 모든 걸 해결해야 한다.

처음 출소했을 때 한 시민단체에서 기금을 마련한다고 붓글씨를 써달라고 해서 ‘여럿이함께’라고 썼다. 한글로 쉽게 액자체로 쓰고 글씨체도 좋은데 문제가 있다고 하더라. ‘여럿이함께’란 메시지 속에는 방법만 있고 목표가 없다고 하더라. 그 뒤로는 글 밑에 ‘여럿이 함께가면 길은 뒤에 나타난다’고 썼다. 쉽게 변화하리라는 낙관적인 생각은 안 하는 게 좋다. 우리 사회가 가진 완고한 구조, 우리가 갇힌 완고한 문맥속에서 무언가를 고민하는 사람은 지극히 적다. 그렇기에 자주 만나 우정을, 음모를 돈독히 해야 한다.

shinyb_main

shinyb_01

shinyb_02

shinyb_03

lecture_sns_mini

2009년 11월 18일 수요일

구글 CEO가 생각하는 5년 뒤의 웹 세상



 @Gartner Symposium/ITxpo Orlando 2009

  • 앞으로 5년 뒤에는 인터넷은 중국어 컨텐츠가 지배할 것이다.
  • 현재의 10대 들이 바라는 웹의 형태가 5년 뒤의 웹의 모델이다.  그들은 앱과 앱 사이를 아무런 거리낌 없이 넘나들고 있으며, 서비스 역시 쉽게 바꾼다.
  • 5년 뒤의 컴퓨터는 현재 보다 훨씬 많은 일을 할 수 있을 것이다.
  • 초고속 통신망 인프라가 더욱 확대되어 TV, 라디오와 같은 대용량의 데이터를 처리하고 이용하는데 아무런 불편함이 없어질 것이다.
  • 구글은 유튜브에서 많은 돈을 벌어들이게 될 것이고, 컨텐츠의 중심도 비디오로 넘어갈 것이다.
  • 실시간 정보의 중요성이 증대될 것이며, 구글 역시 실시간 정보검색 기능을 강화할 것이다.
  • 페이스북과 트위터와 같은 회사들이 많이 나올 것이며, 실시간 웹 서비스 회사들도 많아질 것이다 (이거는 구글의 바램이 아닐지, 춘추전국시대를 바라는 ...)  
  • 5년 뒤에는 전통적인 컨텐츠 제공자(신문, 방송, 잡지 등) 보다 사용자가 만들어낸 정보들이 훨씬 많아지고, 더 많이 소비하는 체제가 확고해지는 근본적인 변화가 가시화 될 것이다. 그러므로, 이런 정보들에 랭킹을 어떻게 매기고, 선별을 할 것인가가 가장 중요하며, 구글은 이 문제를 해결하는 것을 가장 중요한 과제로 생각하고 있다.
  • 구글 크롬 운영체제를 장착한 넷북이 2010년에는 출시가 될 것이며, 여기에는 HTML5 로컬 캐슁 기능이나 오프라인 사용이 원활하게 지원될 것이다.


2009년 10월 10일 토요일

A Library to Last Forever

A Library to Last Forever

Published: October 8, 2009
Mountain View, Calif.

“THE fundamental reasons why the electric car has not attained the popularity it deserves are (1) The failure of the manufacturers to properly educate the general public regarding the wonderful utility of the electric; (2) The failure of [power companies] to make it easy to own and operate the electric by an adequate distribution of charging and boosting stations. The early electrics of limited speed, range and utility produced popular impressions which still exist.”

This quotation would hardly surprise anyone who follows electric vehicles. But it may be surprising to hear that in the year when it was written thousands of electric cars were produced and that year was nearly a century ago. This appeared in a 1916 issue of the journal Electrical World, which I found in Google Books, our searchable repository of millions of books. It may seem strange to look back a hundred years on a topic that is so contemporary, yet I often find that the past has valuable lessons for the future. In this case, I was lucky — electric vehicles were studied and written about extensively early in the 20th century, and there are many books on the subject from which to choose. Because books published before 1923 are in the public domain, I am able to view them easily.

But the vast majority of books ever written are not accessible to anyone except the most tenacious researchers at premier academic libraries. Books written after 1923 quickly disappear into a literary black hole. With rare exceptions, one can buy them only for the small number of years they are in print. After that, they are found only in a vanishing number of libraries and used book stores. As the years pass, contracts get lost and forgotten, authors and publishers disappear, the rights holders become impossible to track down.

Inevitably, the few remaining copies of the books are left to deteriorate slowly or are lost to fires, floods and other disasters. While I was at Stanford in 1998, floods damaged or destroyed tens of thousands of books. Unfortunately, such events are not uncommon — a similar flood happened at Stanford just 20 years prior. You could read about it in The Stanford-Lockheed Meyer Library Flood Report, published in 1980, but this book itself is no longer available.

Because books are such an important part of the world’s collective knowledge and cultural heritage, Larry Page, the co-founder of Google, first proposed that we digitize all books a decade ago, when we were a fledgling startup. At the time, it was viewed as so ambitious and challenging a project that we were unable to attract anyone to work on it. But five years later, in 2004, Google Books (then called Google Print) was born, allowing users to search hundreds of thousands of books. Today, they number over 10 million and counting.

The next year we were sued by the Authors Guild and the Association of American Publishers over the project. While we have had disagreements, we have a common goal — to unlock the wisdom held in the enormous number of out-of-print books, while fairly compensating the rights holders. As a result, we were able to work together to devise a settlement that accomplishes our shared vision. While this settlement is a win-win for authors, publishers and Google, the real winners are the readers who will now have access to a greatly expanded world of books.

There has been some debate about the settlement, and many groups have offered their opinions, both for and against. I would like to take this opportunity to dispel some myths about the agreement and to share why I am proud of this undertaking. This agreement aims to make millions of out-of-print but in-copyright books available either for a fee or for free with ad support, with the majority of the revenue flowing back to the rights holders, be they authors or publishers.

Some have claimed that this agreement is a form of compulsory license because, as in most class action settlements, it applies to all members of the class who do not opt out by a certain date. The reality is that rights holders can at any time set pricing and access rights for their works or withdraw them from Google Books altogether. For those books whose rights holders have not yet come forward, reasonable default pricing and access policies are assumed. This allows access to the many orphan works whose owners have not yet been found and accumulates revenue for the rights holders, giving them an incentive to step forward.

Others have questioned the impact of the agreement on competition, or asserted that it would limit consumer choice with respect to out-of-print books. In reality, nothing in this agreement precludes any other company or organization from pursuing their own similar effort. The agreement limits consumer choice in out-of-print books about as much as it limits consumer choice in unicorns. Today, if you want to access a typical out-of-print book, you have only one choice — fly to one of a handful of leading libraries in the country and hope to find it in the stacks.

Readers' Comments

I wish there were a hundred services with which I could easily look at such a book; it would have saved me a lot of time, and it would have spared Google a tremendous amount of effort. But despite a number of important digitization efforts to date (Google has even helped fund others, including some by the Library of Congress), none have been at a comparable scale, simply because no one else has chosen to invest the requisite resources. At least one such service will have to exist if there are ever to be one hundred.

If Google Books is successful, others will follow. And they will have an easier path: this agreement creates a books rights registry that will encourage rights holders to come forward and will provide a convenient way for other projects to obtain permissions. While new projects will not immediately have the same rights to orphan works, the agreement will be a beacon of compromise in case of a similar lawsuit, and it will serve as a precedent for orphan works legislation, which Google has always supported and will continue to support.

Last, there have been objections to specific aspects of the Google Books product and the future service as planned under the settlement, including questions about the quality of bibliographic information, our choice of classification system and the details of our privacy policy. These are all valid questions, and being a company that obsesses over the quality of our products, we are working hard to address them — improving bibliographic information and categorization, and further detailing our privacy policy. And if we don’t get our product right, then others will. But one thing that is sure to halt any such progress is to have no settlement at all.

In the Insurance Year Book 1880-1881, which I found on Google Books, Cornelius Walford chronicles the destruction of dozens of libraries and millions of books, in the hope that such a record will “impress the necessity of something being done” to preserve them. The famous library at Alexandria burned three times, in 48 B.C., A.D. 273 and A.D. 640, as did the Library of Congress, where a fire in 1851 destroyed two-thirds of the collection.

I hope such destruction never happens again, but history would suggest otherwise. More important, even if our cultural heritage stays intact in the world’s foremost libraries, it is effectively lost if no one can access it easily. Many companies, libraries and organizations will play a role in saving and making available the works of the 20th century. Together, authors, publishers and Google are taking just one step toward this goal, but it’s an important step. Let’s not miss this opportunity.

http://www.nytimes.com/2009/10/09/opinion/09brin.html?_r=1&partner=rss&emc=rss

2009년 10월 3일 토요일

브라우저란 무엇인가


뉴욕 타임스퀘어에서 50명의 사람들에게 "브라우저란 무엇인가?" 에 대해 물었다.
각기 다른 대답들.
굳이 자동차에 가솔린이 들어가서 어떻게 동작되는 지를 몰라도 운전을 하듯이,
사람들에게 '정의'는 중요치 않은 것 같다.
그보다는 그들이 어떻게 '브라우저' 를 이용하고 느끼고 있는지가 중요한듯하다.

2009년 10월 1일 목요일

방통위, 스마트폰에 와이파이 채택 유도키로

  방송통신위원회는 스마트폰 보급 확산 및 모바일인터넷 시장 활성화를 위해 이동통신업체들에게 스마트폰을 포함한 휴대폰에 와이파이(Wi-Fi) 접속기능을 기본적으로 탑재토록 유도하기로 했다고 밝혔다.


이는 이동 중에는 이동통신망을 이용해 모바일인터넷을 이용하거나 착신전환 등으로 와이브로 서비스를 이용하고, 고정된 곳에서는 와이파이를 통해 유선 초고속인터넷을 무료로 이용할 수 있는 환경을 마련하겠다는 취지라고 방통위는 설명했다.

이를 통해 이용자는 요금에 대한 부담을 상당부분 줄이면서 무선인터넷을 자유롭게 이용할 수 있고, 이통업체는 성장이 정체된 음성통화 매출의 문제를 극복하고 새로운 시장을 창출하는 효과가 있을 것이라고 방통위는 말했다.

한편 방통위는 휴대폰 이용자가 음원, 게임, 동영상 등 휴대폰용 컨텐츠를 PC로 우선 다운로드한 후 이를 휴대폰으로 전송하는 이른바, 사이드로딩(Side loading)을 전면적으로 허용토록 하겠다고 밝혔다. 이용자들은 불필요한 무선 데이터통화료를 지불하지 않아도 되고, 컨텐츠제공업체들은 휴대폰용 컨텐츠를 이통사에 종속 받지 않고 판매할 수 있게 된다고 방통위는 말했다.


http://www.smartphonenow.kr/archives/1493

작성 SmartNow - 2009/09/30 – 14:25



Wi-fi 기능을 기본적으로 탑재하는 정책을 추구하는 동시에, 사이드로딩의 전면허용을 통한다는것은, PC sync가 정말로 활성화 될 수 있겠다는 생각이 들게 한다.

하루만 기사 빨리나오지....

2009년 9월 23일 수요일

MP/ PP/ EP

MP: Mass Production : 말 그대로 대량생산(양산)이라고 표현합니다.

       즉, 개발과정 및 초도품 생산 등을 통하여 생산 및 품질상에 문제가 없다고 판단하여  

       대량생산체제로 진행한다는 것입니다.

 

PP: Pre-Production :  생산공정의 적합성 확인 및 제품의 성능,안전성 및 신뢰성 검토와 양

              산시 발생 가능한 문제점을 해결하기 위해 실시하는 예비 시험 생산

 

E/S : Engineer  Sample  : 양산용부품과 금형을 이용한 기구물로 sample를 제작하고, 제품의

             기능, 성능, 안정성,신뢰성 등을 검토하며, 고객 승인를 받기 위한 개발

             초기  SAMPLE

 

EP: Engineer saple Production 쯤 되겠네요. 물론, E/S 을 생산하기 위한 것입니다.

2009년 9월 22일 화요일

Stantum, Sitronix 제휴

Stantum, Sitronix와 제휴 가전 및 모바일 기기의 고성능 멀티 터치 컨트롤러 공급
Stantum and Sitronix Team to Meet Demand for Cost-Effective, High-Performance Multi-Touch in Consumer and Mobile Applications [06-30 15:08]
더보기 ≫
(보르도=뉴스와이어) 2009년 06월 30일 -- 멀티 터치 기술의 개척자적 개발업체인 Stantum(www.stantum.com)과 LCD 드라이버 및 SoC IC 설계분야의 글로벌 리더인 Sitronix는 전압 매트릭스 멀티 터치 싱글 칩 솔루션을 제공하기 위해 제휴를 한다고 발표했다.

라이선스 계약을 통해, Sitronix는 Stantum의 멀티 터치 스크린 특허 기술을 자사의 제품에 통합하여 가전 및 모바일 기기용으로 고성능 멀티 터치 컨트롤러를 공급할 예정이다.

멀티 터치 스크린 시장은 현재 휴대폰, PND 및 MID 그리고 태블릿 PC 및 노트북과 같은 좀 더 큰 스크린을 갖춘 기기들로 구분될 수 있다. Stantum 전압 매트릭스 멀티 터치는 입증된 기술로 설계되어 2004년부터 실제 제품에 적용되고 있으며 특히 모바일 및 가전 제품에 아주 적합한 것으로 인정받고 있다.

“이 파트너 관계는 이전에 없었던 성능을 갖춘 경제적인 멀티 터치 컨트롤러를 원하는 시장 수요를 충족시켜 줄 것이다.”라고 에띠엔느 파야르(Etienne Paillard) Stantum CEO는 밝혔다.

웨버 치엔(Weber Chien) Sitronix 부사장은 다음과 같이 말했다. “Stantum의 기술은 현재 시장에서 가장 앞선 그리고 입증된 멀티 터치 기술이며 당사는 이 기술을 가전 시장에 도입할 수 있는 기회를 갖게 된 것을 아주 기쁘게 생각한다.”

Stantum 기술 기반의 첫 Sitronix 제품은 터치 패널 사양에 따라 소형에서 최대 10.1 인치까지의 중형 터치 패널을 구동시킬 수 있다. 또한 대형 터치 패널을 제어하기 위해 2개 혹은 그 이상의 칩을 단계적으로 접속할 수 있다.

이 제품은 Stantum의 멀티 터치 기술과 Sitronix IC 설계 통합으로 인한 최신 역량을 마음껏 누릴 수 있다. 무한 터치, 손가락 및 스타일러스 펜 입력(필기 인식을 위한 필수 요소), 손가락 압력 감지 그리고 스캔 속도 및 전력 소비 측면에서 타의 추종을 불허하는 성능 등이 이 제품에서 누릴 수 있는 혜택이다.

이 격조와 경제성을 겸비한 솔루션의 첫 번째 샘플은 2009년 제3분기에 입수할 수 있으며 대량 생산은 2009년 제4분기에 이루어진다. 가격은 Sitronix에 연락하여 확인할 수 있다.

추가 정보는 Sitronix의 웹사이트 www.sitronix.com.tw 그리고Stantum의 웹사이트 www.stantum.com에서 확인할 수 있다.

Stantum 소개
Stantum은 2002년부터 멀티 터치 디스플레이 기술을 선도해 온 기업으로 2005년 진정으로 신뢰할 수 있는 멀티 터치 사용자 인터페이스를 사용하는 상용 제품을 처음 출시한 바 있다. 현재, Stantum의 획기적인 기술 포트폴리오를 터치 패널, 컨트롤러, 지적 재산권 핵심 및 소프트웨어 프레임워크 등 멀티 터치 인터렉션의 모든 측면을 다루는 제품을 위해 라이선스 형태로 제공하고 있다. Stantum의 본사는 프랑스 보르도에 있다.

Sitronix 소개
Sitronix Technology Corporation은 유수의 팹리스 LCD 드라이버 IC 및 SoC IC(마이크로컨트롤러) 공급업체이다. 동사는1998년 대만 신추에서 설립되었으며 2003년 12월부터 타이페이 증시에 상장되었다. LCD 드라이버 IC는 휴대폰, OA 기기(프린터, 팩스기, 복사기 및 DECT폰), IA 기기(PDA, 다기능 전자 사전 및 다중언어 전자 번역기) 등에 사용된다. 관련링크 :
  • Sitronix: http://www.sitronix.com.tw
  • Stantum 소개: Stantum은 2002년부터 멀티 터치 디스플레이 기술을 선도해 온 기업으로 2005년 진정으로 신뢰할 수 있는 멀티 터치 사용자 인터페이스를 사용하는 상용 제품을 처음 출시한 바 있다. 현재, Stantum의 획기적인 기술 포트폴리오를 터치 패널, 컨트롤러, 지적 재산권 핵심 및 소프트웨어 프레임워크 등 멀티 터치 인터렉션의 모든 측면을 다루는 제품을 위해 라이선스 형태로 제공하고 있다. Stantum의 본사는 프랑스 보르도에 있다.
    출처: Stantum
    홈페이지: http://www.stantum.com
    언론문의처
    Stantum
    Neal Leavitt
    Leavitt Communications
    +33 760-639-2900
    +33 760-212-9112
    Neal@leavcom.com

    Sitronix
    Vivian Lin
    Vivian_lin@sitronix.com.tw
    여기를 눌러 Stantum 전체 보도자료를 보세요.

    2009년 9월 21일 월요일

    93년에서 바라본 미래 AT&T Ads

     

     

    93년,

    꿈돌이가 나오는 대전엑스포에서 봤던 전기자동차와 우주모형 등에 대한 기억이난다.

     

    93년 AT&T는

    e-book, navigation, tablet, highpass, kiosk, 화상전화, 음성인식, 병원 crm, 화상회의, IPTV, e-learning 을 할 수 있게 해주겠다는 광고를 만들었고,

     

    이러한 비전이

    16년이 지난 지금 이들 대다수를 현실화되게하였다.

     

     

    You will

    2009년 9월 3일 목요일

    Pull-up resistor

    Pull-up resistor

    From Wikipedia, the free encyclopedia

    Pull-up resistors are used in electronic logic circuits to ensure that inputs to logic systems settle at expected logic levels if external devices are disconnected. Pull-up resistors may also be used at the interface between two different types of logic devices, possibly operating at different power supply voltages.

    The idea of a pull-up resistor is that it weakly "pulls" the voltage of the wire it's connected to towards 5V (or whatever voltage represents a logic "high"). However, the resistor is intentionally weak (high-resistance) enough that, if something else strongly pulls the wire toward 0V, the wire will go to 0V. An example of something that would strongly pull a wire to 0V would be the transistor in anopen-collector output.

    Similarly, pull-down resistors are used to hold the input to a zero (low) value when no other component drives the input. They are used less often than pull-up resistors. Pull-down resistors can safely be used with CMOS logic gates because the inputs are voltage-controlled. TTL logic inputs that are left un-connected inherently float high, thus they require a much lower valued pull-down resistor to force the input low. This also consumes more current. For that reason, pull-up resistors are preferred in TTL circuits.

    In bipolar logic families operating at 5 VDC, a typical pull-up resistor value will be 1000–5000 Ω, based on the requirement to provide the required logic level current over the full operating range of temperature and supply voltage. For CMOS and MOS logic, much higher values of resistor can be used, several thousand to a million ohms, since the required leakage current at a logic input is small.

    A circuit showing a pull-up resistor (R2) and a pull-down resistor (R1)

    Pull-up resistors may be used at logic outputs where the logic device cannot source current, such as open-collector TTL logic devices. Such outputs are used for driving external devices, for a wire-OR function in combinatorial logic, or for a simple way of driving a logic bus with multiple devices connected to it. For example, the circuit shown on the right uses 5 V logic level inputs to actuate a relay. If the input is left unconnected, pull-down resistor R1 ensures that the input is pulled down to a logic low. The 7407 TTL device, an open collector buffer, simply outputs whatever it receives as input, but as an open collector device, the output is left effectively unconnected when outputting a "1". Pull-up resistor R2 thus pulls the output all the way up to 12 V when the buffer outputs a "1", providing enough voltage to turn the power MOSFET all the way on and actuate the relay.

    Pull-up resistors may be discrete devices mounted on the same circuit board as the logic devices. Many microcontrollers intended for embedded control applications have internal, programmable pull-up resistors for logic inputs so that minimal external components are needed.

    Some disadvantages of pull-up resistors are the extra power consumed when current is drawn through the resistor, and the reduced speed of a pull-up compared to an active current source. Certain logic families are susceptible to power supply transients introduced into logic inputs through pull-up resistors, which may force the use of a separate filtered power source for the pull-ups.

    [edit]I²C

    Pull-up resistors are needed on the clock and data line for an I²C circuit because they are open-collector pins on the chips

    I²C requires pull-up resistors on its clock (SCL) and data line (SDA) because the pins on the chips are of open-collector design. This means that a chip can only pull the lines low, otherwise they float up to VDD. In I²C, pulling the line to ground indicates a logical zero while letting it float to VDD is a logical one. As a channel access method, this allows one node to determine if another is transmitting by sensing that when asserting a logical 1 (letting it float) and sensing if the line is still at a logical 1 (no other node is pulling the line to ground) then it's possible no other node is simultaneously transmitting. However, if a second node pulls the line to zero then the first node can detect that the other is transmitting.

    [edit]References

    [edit]External links

    2009년 8월 31일 월요일

    360' video - yellowBird

     

    영상을 내 맘대로 돌려가며 볼 수 있다니 놀라운 기술이다!

    다음,구글지도에서 제공하는 스트리트 뷰는 정지영상이었지만, 동영상을 돌려가면서 볼수있다니 대단!

    2009년 8월 16일 일요일

    Windows 출시와 PC판매량간의 상관관계


    윈도우 출시된 시점에서 분명 Microsoft의 매출과 영업이익은 크게 증가했는데,
    PC 판매량은 이를 따라오지 않는 것으로 위의 다이어그램에서 나타난다.
    02년 XP가 출시고 PC판매량은 03년 Q1-Q3에 급격히 증가하지만, MS의 매출은 그닥 변화를 보이지 않는다. 심지어 99년에는 PC판매량이 엄청나게 증가함에도 불구하고, MS의 매출은 줄어든다.

    분명히 윈도우 판매량이 증가한다는 것은 PC에 기본적으로 깔려 판매되는 양이, 개인 소비
    자가 따로 OS를 구매하는 양보다 현격히 클텐데 이런 결과가 나오는 것은, 1번 그래프에서 나타내는 윈도우 출시 시점은 윈도우 출시 '발표' 시점이고, 정말로 PC vendor 들에게 넘어가 각 PC에 적용이 되기까지의 시간차 때문에 아래와 같은 결과가 나오는 것인가?

    윈도우 7이 출시되면 올 연말에는 PC 판매량이 증가할 것이라 예상을 하고, PC제조업체들이 다양한 제품을 출시준비하며 호조를 기대하고 있지만..
    새로운 OS의 등장이 정말 PC 판매증가로 이어지는지,
    아니면 다른 gadget들 처럼 오히려 당시의 경기변동이 더 영향을 미치는 것인지는 조사를 더 해봐야겠다.

    cf> PC shipments to decrease 4.5 percent in 2009 - cnet news March 5, 2009

    2009년 8월 6일 목요일

    HOOKING

    API Hooking Revealed

    [역자주] 이 글은 CodeProject 사이트에 Ivo Ivanov가 "API hooking revealed"라는 제목으로 게재한 글입니다. Win32 시스템에서 API를 후킹하는 방법에 대한 전반적인 기법들을 다루고 있으며 자세한 설명이나 코드보다는 개념적인 내용들이 많아 Win32 SDK에 익숙치 않은 개발자들도 쉽게 접근할 수 있는 좋은 글인 것 같습니다. 원래 소스 파일이 함께 첨부되어 게재된 글인데 이 파일을 번역한 글과 함께 올리는 것은 혹시 저작권 문제가 될 수도 있다고 생각되어 따로 첨부하지 않았습니다. 소스 파일이 필요하신 분은 원문인 "API hooking revealed"에서 다운받아 사용하시기 바랍니다.
    이 글을 읽고 제대로 이해하려면 최소한 윈도우즈 메시지 후킹DLL의 기본 구조에 대해서는 알아야 합니다. 이런 내용들은 MSDN에 잘 설명되어 있고 codeproject, codeguru, devpia 등의 사이트에도 좋은 글들이 많이 게재되어 있으니 참고하시기 바랍니다.

    어떤 윈도우즈 어플리케이션을 개발하기 위해서 우리들은 여러 종류의 언어나 도구들을 사용할 수 있습니다. Visual Basic, Visual C++, Delphi, C++ Builder, PowerBuilder 등 수많은 언어와 도구들이 있습니다.
    이런 프로그램들에서 어떤 작업을 수행하기 위해서 사용하는 방법은 서로 다를지라도 그 내부로 들어가 보면 결국에는 윈도우즈 운영체제에서 제공하는 API를 호출하게 됩니다. 예를 들어 화면에 문자열을 출력하려고 한다면 MFC에서는 CDC::DrawText를 사용하고 Dephi에서는 TCanvas::TextOut을 사용합니다. 도구마다 사용하는 형태는 이렇게 다르지만 결국에는 TextOutA/W API를 호출합니다.
    TextOutA/W API는 gdi32.dll에 구현되어 있는 함수이고 운영체제가 제공하는 API입니다. 윈도우즈는 기본적으로 3개의 DLL-kernel32.dll, user32.dll, gdi32.dll-에 대부분의 API를 구현하여 제공하고 어플리케이션은 실행시 자신의 프로세스 주소 공간으로 이들 DLL을 매핑한 후 사용합니다.
    API 후킹은 어떤 프로그램에서 API 호출을 하는 것을 가로채서 개발자가 만든 프로그램의 함수가 처리할 수 있도록 하는 메카니즘을 말합니다. 반드시 윈도우즈의 API일 필요는 없고 단지 DLL에서 구현하여 제공하는 함수이면 됩니다.
    API 후킹은 어떤 언어로 개발된 프로그램에도 적용될 수 있으며 디버깅이나 트레이싱 작업, 모니터링 작업 등에 사용할 수 있으며 소스 코드가 없는 프로그램에 기능을 추가하기 위한 용도로도 사용할 수 있습니다. 그외에도 여러가지 용도로 사용할 수 있지만 굳이 이런 프로그램을 개발할 계획이 아니더라도 윈도우즈 프로그램의 기본적인 원리를 이해하는데 많은 도움이 됩니다.
    API 후킹을 적용하여 만든 프로그램 중에 주위에서 일반적으로 볼 수 있는 것으로는 myQuickFind, 아래한글사전과 같은 전자 사전 프로그램이 있습니다. 이런 프로그램들은 모두 다른 윈도우의 마우스 커서 밑에 있는 단어를 인식할 수 있는 기능을 가지고 있는데 이것은 윈도우즈 메시지 후킹과 API 후킹(TextOutA/W)을 이용한 것입니다.
    또한 크래킹이나 스파이웨어를 개발하는데 악용될 수도 있고 반대로 방지하는 용도로도 사용될 수 있습니다. 어찌되었든 간에 이 글이 윈도우즈 환경에서 개발을 하시는 많은 분들에게 도움이 되기를 바랍니다.

    번역해서 글을 올리는 것이 처음이어서 어색한 부분들이 많습니다. 게다가 저자가 쉼표를 생략하는 동격 명사 구문이나 분사 구문을 많이 사용하였고 번역이 표준화되지 않은 개발 관련 용어들도 많아 더욱 그렇습니다. 그래서 원문과 번역문을 함께 올렸고 번역이 미비하거나 어색한 부분에는 [역자주]를 달아 놓았습니다. 그래도 이상한 부분들은 코멘트를 달아 주시면 가능하면 수정해서 다시 올리도록 하겠습니다.

    Introduction(소개)

    Intercepting Win32 API calls has always been a challenging subject among most of the Windows developers and I have to admit, it's been one of my favorite topics. The term Hooking represents a fundamental technique of getting control over a particular piece of code execution. It provides an straightforward mechanism that can easily alter the operating system's behavior as well as 3rd party products, without having their source code available.

    Win32 API 호출을 가로채는 것은 대다수의 윈도우즈 개발자들 사이에서 항상 도전하는 과제이었으며 내가 가장 좋아하는 주제 중의 하나가 되었다. 후킹이라는 단어는 코드 실행의 특정 부분을 제어할 수 있는 기반 기술을 의미한다. 후킹은 써드 파티 제품뿐 아니라 운영체제의 동작까지도 소스 코드 없이 쉽게 바꿀 수 있는 간편한 메카니즘을 제공한다.

    Many modern systems draw the attention to their ability to utilize existing Windows applications by employing spying techniques. A key motivation for hooking, is not only to contribute to advanced functionalities, but also to inject user-supplied code for debugging purposes.

    많은 현대적인 시스템들이 스파이 기술을 사용하여 기존의 윈도우즈 어플리케이션을 활용하는 것에 관심을 기울이고 있다. 후킹을 연구하는 주요 동기는 향상된 기능을 제공하는 것 뿐 아니라 디버깅을 목적으로 사용자 정의 코드를 침투시키는 것에 있다.

    Unlike some relatively "old" operating systems like DOS and Windows 3.xx, the present Windows OS as NT/2K and 9x provide sophisticated mechanisms to separate address spaces of each process. This architecture offers a real memory protection, thus no application is able to corrupt the address space of another process or in the worse case even to crash the operating system itself. This fact makes a lot harder the development of system-aware hooks.

    DOS, 윈도우즈3.XX와 같이 상대적으로 오래된 운영체제와 달리, NT/2K,9x와 같은 현재의 윈도우즈 OS는 각각의 프로세스의 주소 공간을 분리하는 정교한 메카니즘을 제공한다. 이러한 구조는 실제 메모리 보호를 제공하여 어떠한 어플리케이션도 다른 프로세스의 주소 공간을 변형시키거나 더 나아가 운영 체제 자체를 망가뜨리지 못하도록 한다. 이러한 이유로 시스템 후킹의 개발은 더욱 어려워졌다.

    My motivation for writing this article was the need for a really simple hooking framework, that will offer an easy to use interface and ability to capture different APIs. It intends to reveal some of the tricks that can help you to write your own spying system. It suggests a single solution how to build a set for hooking Win32 API functions on NT/2K as well as 98/Me (shortly named in the article 9x) family Windows. For the sake of simplicity I decided not to add a support do UNICODE. However, with some minor modifications of the code you could easily accomplish this task.

    이 글을 쓰게 된 동기는 사용하기 쉽고 다른 API들을 가로챌 수 있는 매우 간단한 후킹 프레임웍에 대한 필요성 때문이다. 이 글에서 스파이 시스템을 구축하기 위해 필요한 몇가지 트릭들을 밝힐 계획이다. 이 글은 98/Me와 NT/2K 에서 모두 사용할 수 있는 Win32 API 함수 후킹에 대한 하나의 솔루션을 제안한다. 단순하게 하기 위하여 UNICODE에 대한 지원은 추가하지 않기로 하였다. 하지만 코드를 약간 수정하면 UNICODE에 대한 지원을 쉽게 달성할 수 있을 것이다.

    Spying of applications provides many advantages:

    어플리케이션을 스파이하는 것은 다음과 같은 많은 이점을 제공한다:

    • API function's monitoring(API 함수의 감시)
      The ability to control API function calls is extremely helpful and enables developers to track down specific "invisible" actions that occur during the API call. It contributes to comprehensive validation of parameters as well as reports problems that usually remain overlooked behind the scene. For instance sometimes, it might be very helpful to monitor memory related API functions for catching resource leaks.

      API 함수 호출을 제어할 수 있는 능력은 API 호출시 발생하는 보이지 않는 특정 행위를 개발자가 추적할 수 있도록 도와준다. 또한 항상 지나칠 수 있는 문제점들을 보고할 뿐 아니라 매개변수에 대한 종합적인 검증을 할 수도 있다. 예를 들면 메모리와 관련된 API 함수들을 감시하여 리소스 누출을 잡아내는 것에 매우 유용하다.

    • Debugging and reverse engineering(디버깅과 역공학) 
      Besides the standard methods for debugging API hooking has a deserved reputation for being one of the most popular debugging mechanisms. Many developers employ the API hooking technique in order to identify different component implementations and their relationships. API interception is very powerful way of getting information about a binary executable.

      디버깅을 위한 표준적인 방법들을 제외하면 API 후킹은 가장 인기있는 디버깅 메카니즘의 하나라는 평가를 받는다. 많은 개발자들이 API 후킹 기술을 콤포넘트의 서로 다른 구현들과 그들의 관계를 파악하기 위해 사용한다. API 가로채기는 이진 실행 파일에 대한 정보를 얻을 수 있는 매우 강력한 방법이다.

    • Peering inside operating system(운영체제 엿보기) 
      Often developers are keen to know operating system in dept and are inspired by the role of being a "debugger". Hooking is also quite useful technique for decoding undocumented or poorly documented APIs.

      가끔 개발자들은 운영체제에 대해 이해하기를 갈망하고 "디버거"의 역할을 하게 된다. 후킹은 문서화되지 않았거나 빈약하게 문서화된 API를 해석하는데 매우 유용하다.

    • Extending originally offered functionalities(기존 기능의 확장) by embedding custom modules into external Windows applications Re-routing the normal code execution by injecting hooks can provide an easy way to change and extend existing module functionalities. For example many 3rd party products sometimes don't meet specific security requirements and have to be adjusted to your specific needs. Spying of applications allows developers to add sophisticated pre- and post-processing around the original API functions. This ability is an extremely useful for altering the behavior of the already compiled code.

      외부의 윈도우즈 어플리케이션에 사용자 모듈을 삽입하여 기존에 제공되던 기능을 확장하는, 후크를 침투시켜 기존의 코드 실행을 재편성하는 것은 기존 모듈의 기능을 수정하고 확장하는 쉬운 방법을 제공할 수 있다.(???) 예을 들면 많은 써드 파티 제품들이 특별한 보안적 요구 사항없이 특정 기능을 하도록 수정되어야 한다. 어플리케이션 스파이는 개발자가 원본 API 함수의 호출 전,후에 세련된 처리를 추가할 수 있도록 해준다. 이러한 능력은 이미 컴파일된 코드의 동작을 변경하는데 매우 유용하다.

      [역자주] 도저히 첫번째 문장은 매끄러운 번역을 못하겠습니다. 정확히 주어가 무엇인지를 모르겠지만 대략적인 의미는 API 후킹을 이용하여 소스 코드없이 기존의 어플리케이션에 새로운 기능을 추가하거나 동작을 변경할 수 있다는 것입니다.

      Functional requirements of a hooking system(후킹 시스템의 기능적 요구 사항)

      There are few important decisions that have to be made, before you start implementing any kind of API hooking system. First of all, you should determine whether to hook a single application or to install a system-aware engine. For instance if you would like to monitor just one application, you don't need to install a system-wide hook but if your job is to track down all calls to TerminateProcess() or WriteProcessMemory() the only way to do so is to have a system-aware hook. What approach you will choose depends on the particular situation and addresses specific problems.

      API 후킹 시스템 구현을 시작하기 전에 결정해야 할 몇가지 중요한 사항들이 있다. 무엇보다 먼저 하나의 어플리케이션을 후킹할 것인가 아니면 시스템 전역 엔진을 설치할 것인가를 결정해야 한다. 예를 들어 하나의 어플리케이션만을 감시하기 원한다면 시스템 전역 후크를 설치할 필요가 없지만 TerminateProcess() 함수나WriteProcessMemory() 함수에 대한 모든 호출을 추적하는 업무라면 시스템 전역 후크를 설치해야만 한다. 어떤 접근 방법을 선택하는가는 어떠한 상황인가에 달려 있으며 접근 방법들은 각각 특별한 문제점들을 가지고 있다.

      [역자주] system-aware와 system-wide를 모두 "시스템 전역"으로 번역했습니다. system-wide hook는 MSDN에서 윈도우즈 메시지 후킹을 설명하면서 나오는 용어입니다. global hook라는 용어와 같은 의미이며 실행 중인 모든 어플리케이션에 적용되는 메시지 후크를 뜻합니다.
      글을 읽어 가면서 알게 되겠지만 이 글의 주제인 "API 후크"와 MSDN의 "윈도우 메시지 후크"는 관련이 있지만 서로 다른 용어입니다.

      General design of an API spying framework(일반적인 API 후킹 시스템의 설계)

      Usually a Hook system is composed of at least two parts - a Hook Server and a Driver. The Hook Server is responsible for injecting the Driver into targeted processes at the appropriate moment. It also administers the driver and optionally can receive information from the Driver about its activities whereas the Driver module that performs the actual interception.  
      This design is rough and beyond doubt doesn't cover all possible implementations. However it outlines the boundaries of a hook framework.

      Once you have the requirement specification of a hook framework, there are few design points you should take into account:

      • What applications do you need to hook
      • How to inject the DLL into targeted processes or which implanting technique to follow
      • Which interception mechanism to use

      I hope next the few sections will provide answers to those issues.

      일반적으로 후크 시스템은 최소한 2부분, 후크 서버와 드라이버로 구성된다. 후크 서버는 적절한 시점에 목표로 하는 프로세스에 드라이버를 침투시키는 기능을 한다. 또한 드라이버를 관리하며 선택적으로 드라이버에서 활동 정보를 받을 수 있으며 드라이버 모듈은 실질적인 가로채기를 수행한다.
      이러한 설계는 세련되지 않았고 의심할 바 없이 가능성있는 모든 구현을 처리할 수 없다. 하지만 후크 프레임웍의 범위의 윤곽은 잡아준다.

      일단 후크 프레임웍의 요구 사항이 정의되면 기록해 놓아야 할 몇가지 설계 포인트가 있다:

      • 어떤 어플리케이션을 후킹할 것인가
      • 어떻게 DLL을 목표로 하는 프로세스에 침투시킬 것인가 혹은 아래에 설명된 침투 기술 중 어떤 것을 사용할 것인가
      • 어떤 가로채기 메카니즘을 사용할 것인가

      다음의 몇개 섹션에서 이러한 사항들에 대해 설명하겠다.

      Injecting techniques(침투 기술)

      1. Registry(레지스트리) 
        In order to inject a DLL into processes that link with USER32.DLL, you simply can add the DLL name to the value of the following registry key:

        어떤 DLL을 USER32.DLL과 링크되어 있는 프로세스에 침투시키기 위해서는 아래의 레지스트리 키의 값에 DLL의 이름을 추가하기만 하면 된다.

        HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs

        Its value contains a single DLL name or group of DLLs separated either by comma or spaces. According to MSDN documentation [7], all DLLs specified by the value of that key are loaded by each Windows-based application running within the current logon session. It is interesting that the actual loading of these DLLs occurs as a part of USER32's initialization. USER32 reads the value of mentioned registry key and calls LoadLibrary() for these DLLs in its DllMain code. However this trick applies only to applications that use USER32.DLL. Another restriction is that this built-in mechanism is supported only by NT and 2K operating systems. Although it is a harmless way to inject a DLL into a Windows processes there are few shortcomings:

        • In order to activate/deactivate the injection process you have to reboot Windows.
        • The DLL you want to inject will be mapped only into these processes that use USER32.DLL, thus you cannot expect to get your hook injected into console applications, since they usually don't import functions from USER32.DLL.
        • On the other hand you don't have any control over the injection process. It means that it is implanted into every single GUI application, regardless you want it or not. It is a redundant overhead especially if you intend to hook few applications only. For more details see [2] "Injecting a DLL Using the Registry"

        이 키의 값에는 하나의 DLL 이름만 등록할 수도 있고 콤마나 스페이스로 구분하여 여러 개의 DLL들을 등록할 수도 있다. MSDN 문서 [7]에 의하면 이 키의 값으로 등록된 DLL들은 현재의 로그온 세션 내에서 윈도우즈 기반의 어플리케이션이 실행될 때마다 로드된다. 흥미롭게도 이 DLL들의 실제적인 로드는 USER32의 초기화 과정의 일부분으로서 수행된다. USER32는 상기의 레지스트리 키의 값을 읽어DllMain 안에서 이들 DLL에 대해 LoadLibrary() 함수를 호출한다. 그러나 이 방법은 USER32.DLL을 사용하는 어플리케이션에 대해서만 적용할 수 있다. 또다른 제약은 이 메카니즘이 NT와 2K 운영체제에 대해서만 지원된다는 것이다. 이 방법이 어떤 윈도우즈 프로세스에 DLL을 침투시키는 유용한 방법이지만 몇가지 단점들이 있다:

        • 침투 과정을 활성/비활성시키기 위해서는 윈도우즈를 리부팅해야 한다.
        • 침투시킬 DLL은 USER32.DLL을 사용하는 프로세스에만 가능하다. 따라서 USER32.DLL에서 함수들을 임포트하지 않는 콘솔 어플리케이션에 대해서는 후크를 침투시킬 수 없다.
        • 한편으로는 침투 과정에 대한 제어를 전혀 할 수가 없다. 원하건 원하지 않건 간에 모든 GUI 어플리케이션들에 침투하게 된다. 소수의 어플라케이션만 후킹하기를 원하는 경우 이것은 상당한 오버헤드를 유발하게 된다. 보다 자세한 내용은 레퍼런스의 [2] "Injecting a DLL Using the Registry" 를 참조하기 바란다.

      2. System-wide Windows Hooks(시스템 전역 윈도우즈 후크) 
        Certainly a very popular technique for injecting DLL into a targeted process relies on provided by Windows Hooks. As pointed out in MSDN a hook is a trap in the system message-handling mechanism. An application can install a custom filter function to monitor the message traffic in the system and process certain types of messages before they reach the target window procedure.

        목표로 하는 프로세스에 DLL을 침투시키는 매우 인기있는 기술은 윈도우즈 후크를 이용하는 것이다. MSDN에서 설명하듯이 후크는 시스템 상의 메시지 처리 메카니즘을 가로채는 것이다. 어플리케이션은 사용자 정의 필터 함수를 설치하여 시스템에서의 메시지 교환을 감시하고 특정한 종류의 메시지가 목표로 하는 윈도우에 도달하기 전에 처리할 수 있다.

        [역지주] 여기서 말하는 윈도우즈 후크는 API 후크와 다른 용어로서 MSDN에서 설명하고 있는 메시지 후크를 뜻합니다. 혹시 메시지 후크를 전혀 모른다면 MSDN에서 대략적인 의미라도 파악하고서 이 글을 읽으시기 바랍니다.

        A hook is normally implemented in a DLL in order to meet the basic requirement for system-wide hooks. The basic concept of that sort of hooks is that the hook callback procedure is executed in the address spaces of each hooked up process in the system. To install a hook you call SetWindowsHookEx() with the appropriate parameters. Once the application installs a system-wide hook, the operating system maps the DLL into the address space in each of its client processes. Therefore global variables within the DLL will be "per-process" and cannot be shared among the processes that have loaded the hook DLL. All variables that contain shared data must be placed in a shared data section. The diagram bellow shows an example of a hook registered by Hook Server and injected into the address spaces named "Application one" and "Application two".

        후크는 시스템 전역 후크의 기본 요구 사항을 충족시키기 위해서는 보통 DLL로 구현된다. 이러한 종류의 후크는 기본적으로 후크 콜백 프로시져가 시스템 상에서 후크된 각각의 프로세스의 주소 공간에서 실행된다. 후크를 설치하기 위해서는 SetWindowsHookEx() 함수를 적절한 매개변수를 주어 호출하여야 한다. 일단 어플리케이션이 시스템 전역 후크를 설치하면 운영체제는 DLL을 클라이언트 프로세스의 각각의 주소 공간에 매핑하게 된다. 그러므로 DLL 내의 전역 변수는 프로세스마다 존재하게 되고 후크 DLL을 적재한 프로세스 사이에서 공유할 수 없게 된다. 데이터를 공유하는 모든 변수들은 공유 데이터 섹션에 정의되어야만 한다. 아래의 그림은 후크 서버에 의해 등록된 하나의 후크와 "Application one"과 "Application two"라는 이름의 주소 공간에 침투한 후크의 예를 보여준다.

        Figure 1

        A system-wide hook is registered just ones when SetWindowsHookEx() is executed. If no error occurs a handle to the hook is returned. The returned value is required at the end of the custom hook function when a call to CallNextHookEx() has to be made. After a successful call to SetWindowsHookEx() , the operating system injects the DLL automatically (but not necessary immediately) into all processes that meet the requirements for this particular hook filter. Let's have a closer look at the following dummyWH_GETMESSAGE filter function:

        시스템 전역 후크는 SetWindowsHookEx() 함수가 실행될 때 등록된다. 오류가 없으면 후크 핸들이 반환된다. 반환값은 사용자 정의 후크 함수의 끝부분에서 CallNextHookEx() 함수를 호출할 때 필요하다. SetWindowsHookEx() 함수가 성공적으로 호출되면 운영체제는 DLL을 특별한 후크 필터의 요구 사항을 충족시키는 모든 프로세스에 자동적으로(즉시는 아님) 침투시킨다. 아래의 아무것도 하지 않는WH_GETMESSAGE 필터 함수를 보자:

         //--------------------------------------------------------------------------- 
        // GetMsgProc
        //
        // Filter function for the WH_GETMESSAGE - it's just a dummy function
        //---------------------------------------------------------------------------
        LRESULT CALLBACK GetMsgProc(
            int code,       // hook code
            WPARAM wParam,  // removal option
            LPARAM lParam   // message
            )
        {
            // We must pass the all messages on to CallNextHookEx.
            return ::CallNextHookEx(sg_hGetMsgHook, code, wParam, lParam);
        }

         

        A system-wide hook is loaded by multiple processes that don't share the same address space.

        시스템 전역 후크는 동일한 주소 공간을 공유하지 않는 여러 개의 프로세스들에 로드된다.

        For instance hook handle sg_hGetMsgHook, that is obtained by SetWindowsHookEx() and is used as parameter in CallNextHookEx() must be used virtually in all address spaces. It means that its value must be shared among hooked processes as well as the Hook Server application. In order to make this variable "visible" to all processes we should store it in the shared data section.

        예를 들면 SetWindowsHookEx() 호출로 얻어지고 CallNextHookEx() 호출의 매개변수로 사용되는sg_hGetMsgHook는 모든 주소 공간에서 사용된다. 이것은 이 값이 후크 서버 어플리케이션 뿐만 아니라 후크된 프로세스 사이에서도 공유되어야 한다는 것을 의미한다. 이 변수를 모든 프로세스에서 사용 가능하도록 하기 위해서는 이 변수를 공유 데이터 섹션에 저장하여야만 한다.


         
         

        The following is an example of employing #pragma data_seg(). Here I would like to mention that the data within the shared section must be initialized, otherwise the variables will be assigned to the default data segment and #pragma data_seg() will have no effect.

        아래의 예제는 #pragma data_seg()의 사용을 보여준다. 공유 섹션의 데이터들은 반드시 초기화되어야 하며 그렇지 않으면 변수들은 디폴트 데이터 세그먼트에 할당되어 #pragma data_seg()는 아무런 효과도 갖지 않게 된다는 시실을 강조하고 싶다.

        //--------------------------------------------------------------------------- // Shared by all processes variables //--------------------------------------------------------------------------- #pragma data_seg(".HKT") HHOOK sg_hGetMsgHook = NULL; BOOL sg_bHookInstalled = FALSE; // We get this from the application who calls SetWindowsHookEx()'s wrapper HWND sg_hwndServer = NULL; #pragma data_seg() 
        You should add a SECTIONS statement to the DLL's DEF file as well

        DLL의 DEF 파일에도 SECTIONS 문장을 추가하여야 한다.

        SECTIONS .HKT Read Write Shared 
        or use
        #pragma comment(linker, "/section:.HKT, rws") 

        Once a hook DLL is loaded into the address space of the targeted process, there is no way to unload it unless the Hook Server calls UnhookWindowsHookEx() or the hooked application shuts down. When the Hook Server calls UnhookWindowsHookEx() the operating system loops through an internal list with all processes which have been forced to load the hook DLL. The operating system decrements the DLL's lock count and when it becomes 0, the DLL is automatically unmapped from the process's address space.

        Here are some of the advantages of this approach:


         
        • This mechanism is supported by NT/2K and 9x Windows family and hopefully will be maintained by future Windows versions as well.
        • Unlike the registry mechanism of injecting DLLs this method allows DLL to be unloaded when Hook Server decides that DLL is no longer needed and makes a call toUnhookWindowsHookEx()


         

        후크 DLL이 목표로 하는 프로세스에 일단 로드되면 후크 서버가 UnhookWindowsHookEx() 함수를 호출하거나 후크된 어플리케이션을 종료하기 전에는 언로드할 방법이 없다. 후크 서버가UnhookWindowsHookEx() 함수를 호출하면 운영체제는 내부의 리스트를 통해 후크 DLL을 로드하도록 지시했던 모든 프로세스들을 순회하게 된다. 운영체제는 DLL의 참조수를 감소시키고 참조수가 0이 되면 DLL은 자동적으로 프로세스의 주소 공간에서 언매핑된다.

        이러한 접근 방식은 다음과 같은 이점이 가진다:



         
        • 이 메카니즘은 NT/2K와 9X 윈도우즈 패밀리에서 지원되며 다행스럽게도 미래의 윈도우즈에서 계속 지원이 유지될 것이다.
        • DLL을 침투시키는 레지스트리 메카니즘과 달리 이 방법은 후크 서버가 DLL이 더이상 필요없다고 결정하여 UnhookWindowsHookEx() 함수를 호출하게 되면 DLL을 언로드할 수 있다.

         
         

        Although I consider Windows Hooks as very handy injection technique, it comes with its own disadvantages:


         
        • Windows Hooks can degrade significantly the entire performance of the system, because they increase the amount of processing the system must perform for each message.
        • It requires lot of efforts to debug system-wide Windows Hooks. However if you use more than one instance of VC++ running in the same time, it would simplify the debugging process for more complex scenarios.
        • Last but not least, this kind of hooks affect the processing of the whole system and under certain circumstances (say a bug) you must reboot your machine in order to recover it.


        윈도우즈 후크가 매우 편리한 침투 기술이지만 다음과 같은 단점이 있다:


         
        • 윈도우즈 후크는 시스템이 수행하여야 하는 메시지의 처리 과정을 증가시키므로 전체 시스템의 성능을 확연하게 저하시킨다.
        • 시스템 전역 후크를 디버그하는 것은 많은 노력을 필요로 한다. 하지만 동시에 하나 이상의 VC++ 인스턴스를 이용할 있다면 복잡한 디버그 과정을 단순화할 수 있을 것이다.
          [역자주] 어떻게 VC++을 2개 띄운다는 것인지 잘 모르겠습니다. 혹시 아시는 분은 코멘트를 달아 주세요.
        • 마지막이지만 사소하지 않은 것이 이러한 방식의 후크는 전체 시스템의 프로세스에 영향을 미치고 어떤 특별한 상황(버그 발생)에서는 복구하기 위해 시스템을 리부팅해야만 한다.
          [역자주] "Last but not least", 영문을 읽다 보면 자주 나오는 말인데 뭐라 번역을 하는게 좋은지 잘 모르겠습니다. 뜻은 "마지막 사항이지만 그렇다고 해서 덜 중요한 것이 아니다."인데 이렇게 번역하기는 좀 그렇네요.


         

         
      3. Injecting DLL by using CreateRemoteThread() API function (CreateRemoteThread() 함수를 이용한 DLL 침투)

          Well, this is my favorite one. Unfortunately it is
          supported only by NT and Windows 2K operating systems.
          It is bizarre, that you are allowed to call (link with) this API on Win 9x as well, but
          it just returns NULL without doing anything.
         

        이것이 내가 가장 선호하는 방법이다. 불행히도 이 방법은 오직 NT와 2K 운영체제에서만 지원된다. 윈도우즈 9x에서도 이 API를 호출할 수 있지만 아무 것도 하지 않고 그냥 NULL을 반환한다.

        Injecting DLLs by remote threads is Jeffrey Ritcher's idea and is well documented in his article [9] "Load Your 32-bit DLL into Another Process's Address Space Using INJLIB".


         

        리모트 쓰레드를 이용하여 DLL을 침투시키는 것은 Jeffrey Ritcher의 아이디어이며 그의 기사인 [9] "Load Your 32-bit DLL into Another Process's Address Space Using INJLIB"에 잘 설명되어 있다.


         
         

        The basic concept is quite simple, but very elegant. Any process can load a DLL dynamically usingLoadLibrary() API. The issue is how do we force an external process to call LoadLibrary() on our behalf, if we don't have any access to process's threads? Well, there is a function, calledCreateRemoteThread() that addresses creating a remote thread. Here comes the trick - have a look at the signature of thread function, whose pointer is passed as parameter (i.e.LPTHREAD_START_ROUTINE) to the CreateRemoteThread():


         

        기본 개념은 상당히 단순하지만 굉장히 멋지다. 어떤 프로세스도 LoadLibrary() API를 호출하여 DLL을 동적으로 로드할 수 있다. 문제는 어떻게 프로세스의 쓰레드에 대해 전혀 접근을 하지 못하면서 외부의 프로세스가 적절하게 LoadLibrary() 함수를 호출하도록 만드는가 하는 것이다. 하나의 리모트 쓰레드를 생성하는 CreateRemoteThread() 함수가 그 해답이다. 여기서 약간의 속임수가 필요하다. - 쓰레드 함수의 원형을 보라. 이 함수의 포인터가 매개변수(LPTHREAD_START_ROUTINE)로CreateRemoteThread() 함수에 넘겨진다:

        DWORD WINAPI ThreadProc(LPVOID lpParameter);
        And here is the prototype of LoadLibrary API

        그리고 여기 LoadLibrary API의 원형이 있다.


        HMODULE WINAPI LoadLibrary(LPCTSTR lpFileName);


        Yes,
          they do have "identical" pattern. They use the same calling convention WINAPI, they both accept one parameter and the
          size of returned value is the same. This match gives us a hint that we can use
          LoadLibrary() as thread function, which will
          be executed after the remote thread has been created. Let's have a look at the
          following sample code:
         
         

        그렇다, 이 함수들은 동일한 형태를 지닌다. 이 함수들은 같은 호출 규약 WINAPI를 사용하고, 하나의 매개변수를 받아 동일한 크기의 값을 반환한다. 이러한 일치점들은 LoadLibrary() 함수를 쓰레드 함수로 사용하여 리모트 쓰레드가 생성된 후에 실행시킬 수가 있다는 힌트를 준다. 아래의 예제 코드를 살펴보자.


         
        hThread = ::CreateRemoteThread( hProcessForHooking, NULL, 0, pfnLoadLibrary, "C:\\HookTool.dll", 0, NULL); 

         
         

        By using GetProcAddress() API we get the address of the LoadLibrary() API. The dodgy thing here is that Kernel32.DLL is mapped always to the same address space of each process, thus the address of LoadLibrary() function has the same value in address space of any running process. This ensures that we pass a valid pointer (i.e. pfnLoadLibrary) as parameter of CreateRemoteThread().


         

        GetProcAddress() API를 사용하여 우리는 LoadLibrary() API의 주소를 구할 수가 있다. 여기서 이상한 것은 Kernel32.DLL이 각각의 프로세스 공간에서 항상 동일한 주소로 매핑되어 실행 중인 어떤 프로세스의 주소 공간에서도 LoadLibrary()의 주소가 똑같다는 것이다. 이것은CreateRemoteThread() 함수의 매개변수로서 유효한 포인터 (i.e. pfnLoadLibrary)를 넘길 수 있다는 확신을 준다.


         
           

        As parameter of the thread function we use the full path name of the DLL, casting it to LPVOID. When the remote thread is resumed, it passes the name of the DLL to the ThreadFunction (i.e. LoadLibrary). That's the whole trick with regard to using remote threads for injection purposes.


         
         

        쓰레드 함수의 매개변수로 DLL의 전체 경로명을 지정하고 LPVOID로 형변환한다. 리모트 쓰레드가 시작할 때 DLL의 이름이 쓰레드 함수(i.e. LoadLibrary)의 매개변수로 넘겨진다. 이것이 리모트 쓰레드를 사용하여 침투를 하는 속임수의 전부이다.

        [역자주] 혹시 이해가 안가시는 분들을 위해 부연 설명을 하겠습니다. 본인도 쓰레드 작업을 해본 적은 없지만 여기서 말하는 방법은 대강 다음과 같습니다. CreateRemoteThread라는 함수는 다른 프로세스에 쓰레드를 생성하는 함수인데 이 함수는 쓰레드 생성시 초기화를 위한 콜백 함수인 ThreadProc의 주소를 매개변수로 받습니다. 그런데 이 콜백 함수의 원형이 LoadLibrary와 매우 유사하고 ThreadProc는 생성시 단 한번 실행되므로 ThreadProc에 LoadLibrary의 주소를 넘겨 주면 결국 목표로 하는 프로세스가 LoadLibrary를 호출하여 프로세스의 주소 공간에 DLL을 로드하게 된다는 것입니다.

        There is an important thing we should consider, if implanting through CreateRemoteThread() API. Every time before the injector application operate on the virtual memory of the targeted process and makes a call to CreateRemoteThread(), it first opens the process using OpenProcess() API and passes PROCESS_ALL_ACCESS flag as parameter. This flag is used when we want to get maximum access rights to this process. In this scenario OpenProcess() will return NULL for some of the processes with low ID number. This error (although we use a valid process ID) is caused by not running under security context that has enough permissions. If you think for a moment about it, you will realize that it makes perfect sense. All those restricted processes are part of the operating system and a normal application shouldn't be allowed to operate on them. What would happen if some application has a bug and accidentally attempts to terminate an operating system's process? To prevent the operating system from that kind of eventual crashes, it is required that a given application must have sufficient privileges to execute APIs that might alter operating system behavior. To get access to the system resources (e.g. smss.exe, winlogon.exe, services.exe, etc) through OpenProcess() invocation, you must be granted the debug privilege. This ability is extremely powerful and offers a way to access the system resources, that are normally restricted. Adjusting the process privileges is a trivial task and can be described with the following logical operations:



         
        • Open the process token with permissions needed to adjust privileges
        • Given a privilege's name "SeDebugPrivilege", we should locate its local LUID mapping. The privileges are specified by name and can be found in Platform SDK file winnt.h
        • Adjust the token in order to enable the "SeDebugPrivilege" privilege by callingAdjustTokenPrivileges() API
        • Close obtained by OpenProcessToken() process token handle
        For more details about changing privileges see [10] "Using
          privilege".

         
         

        CreateRemoteThread() API를 사용하여 침투하는 경우에는 반드시 고려해야 하는 중요한 사항이 하나 있다. 침투 어플리케이션이 목표로 하는 프로세스의 가상 메모리에서 작동하고CreateRemoteThread()를 호출하기 전에 OpenProcess() API에 PROCESS_ALL_ACCESS 플래그를 매개변수로 넘겨주어 먼저 프로세스를 오픈하여야 한다. 이 플래그는 프로세스에 대한 최대한의 접근 권한을 얻기 위해 사용된다. 이 경우 일부 작은 ID의 프로세스는 OpenProcess() 함수가 NULL을 반환한다. 유효한 프로세스 ID를 사용했음에도 이러한 오류가 나는 것은 충분한 권한을 가지는 보안 레벨에서 실행되지 않았기 때문이다. 이것에 대해 잠시 살펴 보면 정확한 의미를 알 수 있다. 이렇게 제한되는 모든 프로세스는 운영체제의 일부분이고 일반적인 어플리케이션이 이런 프로세스를 조작하는 것은 허용되지 않는다. 어떤 어플리케이션이 버그를 가지고 있어 운영체제의 프로세스를 중지시킬려고 한다면 어떻게 되겠는가? 운영체제를 이러한 유형의 사고로부터 보호하기 위해 어떤 어플리케이션이 운영체제의 동작을 변경할 수 있는 API들을 실행하기 위해서는 충분한 권한을 가져야만 가능하다.OpenProcess() 호출을 통해 시스템 자원(예: smss.exe, winlogon.exe, services.exe..)에 대해 접근하려면 디버그 권한을 가져야만 한다. 이 권한은 매우 강력하며 일반적으로 제한되는 시스템 자원에 대한 접근을 허용한다. 프로세스의 권한을 조정하는 것은 사소한 작업이며 아래에 논리적인 방법을 설명하였다.


         
         
        • 프로세스 토큰을 권한 조정을 위해 필요한 퍼미션으로 오픈한다.
        • 주어진 권한의 이름 "SeDebugPrivilege"으로 LUID매핑을 찾는다. 권한은 이름으로 구분되며 플랫폼 SDK 파일 winnt.h에서 찾을 수 있다.
        • "SeDebugPrivilege" 권한을 활성화하기 위해 AdjustTokenPrivileges() API를 호출하여 토큰을 조정한다.
        • OpenProcessToken()으로 얻은 프로세스 토큰 핸들을 닫는다.

         

        권한 변경에 관한 보다 자세한 설명은 [10] "Using privilege"를 참조한다.

      4. Implanting through BHO add-ins(BHO 애드인을 통한 침투)
        Sometimes you will need to inject a custom code inside Internet Explorer only. Fortunately Microsoft provides an easy and well documented way for this purpose - Browser Helper Objects. A BHO is implemented as COM DLL and once it is properly registered, each time when IE is launched it loads all COM components that have implemented IObjectWithSite interface.

        때때로 인터넷 익스플로러에만 사용자 정의 코드를 침투시키는 것이 필요할 수 있다. 다행스럽게도 마이크로소프트는 이러한 목적에 부합하는 쉽고 잘 문서화된 Brower Helper Object라는 방법을 제공한다. BHO는 COM DLL로 구현되며 적절하게 등록되기만 하면 IE가 실행될 때마다 IE가IObjectWithSite 인터페이스를 구현한 모든 COM 객체를 로드한다.


         
         
      5. MS Office add-ins(오피스 애드인)

          Similarly, to the BHOs, if you need to implant in MS Office applications code of your
          own, you can take the advantage of provided standard mechanism by implementing
          MS Office add-ins. There are many available samples that show how to implement
          this kind of add-ins.

         

         
         

        BHO와 유사하게 MS 오피스에 자신의 코드를 침투시키려면 MS 오피스 애드인으로 구현되는 표준 메카니즘의 장점을 이용할 수 있다. 이러한 종류의 애드인을 구현하는 방법을 설명하는 예제들은 많이 있다.




      Interception mechanisms(가로채기 메카니즘)



      Injecting a DLL into the address space of an external process is a key element of a spying system. It provides an excellent opportunity to have a control over process's thread activities. However it is not sufficient to have the DLL injected if you want to intercept API function calls within the process.


      다른 프로세스의 주소 공간에 DLL을 침투시키는 것은 스파이 시스템의 중요한 요소이다. 이것은 프로세스의 쓰레드 활동에 대해 제어할 수 있는 훌륭한 기회를 제공한다. 그러나 프로세스 내의 API 함수 호출을 가로채려면 DLL을 침투시키는 것만으로는 충분치 않다.



      This part of the article intends to make a brief review of several available real-world hooking aspects. It focuses on the basic outline for each one of them, exposing their advantages and disadvantages.


      지금부터 실제 후킹의 여러가지 형태에 대해 간단하게 살펴 보겠다. 각각의 기본적인 윤곽에 초점을 맞추고 장점과 단점을 설명하겠다.



      In terms of the level where the hook is applied, there are two mechanisms for API spying - Kernel level and User level spying. To get better understanding of these two levels you must be aware of the relationship between the Win32 subsystem API and the Native API. Following figure demonstrates where the different hooks are set and illustrates the module relationships and their dependencies on Windows 2K:


      후크가 적용되는 레벨의 측면에서 보면 API 후킹은 커널 레벨과 사용자 레벨의 2가지 메카니즘으로 구분된다. 이 2가지 레벨에 대한 이해를 돕기 위해 설명하자면 Win32 서브시스템 API와 네이티브 API의 관계를 알아야만 한다. 아래의 그림은 다른 종류의 후크가 설치되는 위치를 보여주며 윈도우즈 2K에서 모듈 간의 관계와 의존성을 표시하고 있다.


      Figure 2

       

      The major implementation difference between them is that interceptor engine for kernel-level hooking is wrapped up as a kernel-mode driver, whereas user-level hooking usually employs user-mode DLL.


      이들을 구현함에 있어 가장 중요한 차이점은 커널 레벨 후킹의 가로채기 엔진은 커널 모드 드라이버로 포장되지만 사용자 레벨 후킹은 일반적으로 사용자 모드 DLL을 사용한다는 것이다.




         
      1. NT Kernel level hooking(NT 커널 레벨 후킹) 
         

        There are several methods for achieving hooking of NT system services in kernel mode. The most popular interception mechanism was originally demonstrated by Mark Russinovich and Bryce Cogswell in their article [3] "Windows NT System-Call Hooking". Their basic idea is to inject an interception mechanism for monitoring NT system calls just bellow the user mode. This technique is very powerful and provides an extremely flexible method for hooking the point that all user-mode threads pass through before they are serviced by the OS kernel.

        커널 모드에서 NT 시스템 서비스의 후킹을 하기 위해서는 몇가지 방법들이 있다. 가장 인기있는 가로채기 메카니즘은 Mark Russinovich와 Bryce Cogswell이 그들의 글 [3] "Windows NT System-Call Hooking"에서 처음 소개하였다. 그들의 기본 아이디어는 NT 시스템 호출을 감시하기 위한 가로채기 메카니즘을 단지 사용자 모드 하부에 침투시키는 것이다.(???)

        [역자주] 도저히 해석을 못하겠습니다. 일단 bellow(소리치다,울부짖다)가 아니라 below(~밑에)인 것 같은데...
        이 기술은 매우 강력하며 모든 사용자 모드 쓰레드들이 OS 커널에 의해 서비스되기 전에 거쳐야 하는 지점을 후킹하는 굉장히 유연한 방법을 제공한다.

        You can find an excellent design and implementation in "Undocumented Windows 2000 Secrets" as well. In his great book Sven Schreiber explains how to build a kernel-level hooking framework from scratch [5].

        "Undocumented Windows 2000 Secrets" [5]에서도 뛰어난 설계와 구현을 발견할 수 있다. 이 훌륭한 책에서 Sven Schreiber는 어떻게 커널 레벨 후킹 프레임웍을 구축하는가를 개략적으로 설명하였다.

        Another comprehensive analysis and brilliant implementation has been provided by Prasad Dabak in his book "Undocumented Windows NT" [17].

        또다른 폭넓은 분석과 명석한 구현을 Prasad Dabak의 책 "Undocumented Windows NT" [17]에서도 찾을 수 있다.

        However, all these hooking strategies, remain out of the scope of this article.


         

        하지만 이러한 모든 후킹 전략들은 이 글의 범위를 벗어난다.


         
      2. Win32 User level hooking(Win32 사용자 레벨 후킹)

         
         

             
        1. Windows subclassing.(윈도우즈 서브클래싱)

              This
              method is suitable for situations where the application's behavior might be
              changed by new implementation of the window procedure. To accomplish this
              task you simply call SetWindowLongPtr() 
              with GWLP_WNDPROC parameter and pass the
              pointer to your own window procedure. Once you have the new subclass
              procedure set up, every time when Windows dispatches a message to a
              specified window, it looks for the address of the window's procedure
              associated with the particular window and calls your procedure instead of
              the original one.
             

          이 방법은 어플리케이션의 동작이 윈도우 프로시저를 새롭게 구현하여 변경될 수 있는 상황에 적합하다. 이 작업을 하기 위해서는 GWLP_WNDPROC를 매개변수로 하여SetWindowLongPtr() 함수를 호출하고 새로운 윈도우 프로시저의 포인터를 넘겨 주기만 하면 된다. 일단 새로운 서브클래스 프로시저가 설정되면 윈도우즈는 메시지를 특정 윈도우로 보낼 때마다 특정 윈도우와 연관된 윈도우 프로시저의 주소를 파악해서 기존의 프로시저 대신 새로운 프로시저를 호출하게 된다.

          The drawback of this mechanism is that subclassing is available only within the boundaries of a specific process. In other words an application should not subclass a window class created by another process.

          Usually this approach is applicable when you hook an application through add-in (i.e. DLL / In-Proc COM component) and you can obtain the handle to the window whose procedure you would like to replace.

          For example, some time ago I wrote a simple add-in for IE (Browser Helper Object) that replaces the original pop-up menu provided by IE using subclassing.

          이 메카니즘의 단점은 서브클래싱이 하나의 특정 프로세스의 영역으로만 제한된다는 것이다. 바꿔 말하면 하나의 어플리케이션은 다른 어플리케이션에 의해 생성된 윈도우 클래스는 서브클래싱을 할 수가 없다.

          일반적으로 이러한 접근 방법은 애드인(i.e. DLL / In-Proc COM component)을 통해 후킹하고 교체하려는 프로시저의 윈도우 핸들을 구할 수 있는 경우에 유용하다.

          예를 들면, 얼마 전에 나는 IE가 사용하는 원래의 팝업 메뉴를 서브클래싱을 이용하여 교체하는 간단한 IE 애드인(BHO) 작성하였다.

        2. Proxy DLL (Trojan DLL)(대리자 DLL)
          An easy way for hacking API is just to replace a DLL with one that has the same name and exports all the symbols of the original one. This technique can be effortlessly implemented using function forwarders. A function forwarder basically is an entry in the DLL's export section that delegates a function call to another DLL's function.

          API를 해킹하는 쉬운 방법은 같은 이름을 가지고 원본과 동일한 익스포트 심볼을 가지는 DLL로 바꿔치는 것이다. 이 기술은 함수 포워더를 이용하여 쉽게 구현할 수 있다. 함수 포워더는 기본적으로 함수에 대한 호출을 다른 DLL의 함수로 위임하는 DLL 익스포트 섹션의 엔트리이다.

          You can accomplish this task by simply using #pragma comment:

          이 작업은 단순히 #pragma comment을 이용하여 구현할 수 있다:

          #pragma comment(linker, "/export:DoSomething=DllImpl.ActuallyDoSomething")

          However, if you decide to employ this method, you should take the responsibility of providing compatibilities with newer versions of the original library. For more details see [13a] section "Export forwarding" and [2] "Function Forwarders".

          그러나 이 방법을 사용하기로 한다면 원본 라이브러리와 새로운 버전이 호환되도록 유지하여야 한다. 자세한 내용은 [13a] "Export forwarding" 과 [2] "Function Forwarders"을 참조하기 바란다.

        3. Code overwriting(코드 덮어쓰기)
          There are several methods that are based on code overwriting. One of them changes the address of the function used by CALL instruction. This method is difficult, and error prone. The basic idea beneath is to track down all CALL instructions in the memory and replace the addresses of the original function with user supplied one.

          코드 덮어쓰기에 기초한 몇가지 방법들이 있다. 그중 하나는 CALL 명령에 의해 사용되는 함수의 주소를 변경하는 것이다. 이 방법은 어렵고 오류를 발생시키기 쉽다. 기본적인 아이디어는 메모리 상의 모든 CALL 명령을 추적하고 원본 함수의 주소를 사용자가 정의한 주소로 바꾸는 것이다.

          [역자주] 이 부분은 본인이 어셈블리에 대한 지식이 미흡하고 어차피 내용 자체가 이 글의 주제를 벗어나기 때문에 대강 해석하였습니다.

          Another method of code overwriting requires a more complicated implementation. Briefly, the concept of this approach is to locate the address of the original API function and to change first few bytes of this function with a JMP instruction that redirects the call to the custom supplied API function. This method is extremely tricky and involves a sequence of restoring and hooking operations for each individual call. It's important to point out that if the function is in unhooked mode and another call is made during that stage, the system won't be able to capture that second call.
          The major problem is that it contradicts with the rules of a multithreaded environment.

          However, there is a smart solution that solves some of the issues and provides a sophisticated way for achieving most of the goals of an API interceptor. In case you are interested you might peek at [12] Detours implementation.

          코드 덮어쓰기의 또다른 방법은 보다 복잡한 구현을 필요로 한다. 간단하게 설명하면 이 접근의 개념은 원본 API 함수의 주소를 파악하고 이 함수의 첫번째 몇 바이트를 사용자 정의 API 함수로 연결시키는 JMP 명령으로 변경하는 것이다. 이 방법은 매우 교묘하고 각각의 개별적인 호출에 대해 일련의 복원과 후킹을 반복하게 한다. 만일 함수가 후크되지 않은 상태에서 다른 호출이 발생하면 시스템은 두번째 호출을 가로챌 수 없다는 것은 매우 중요하다.
          가장 큰 문제점은 멀티쓰레드 환경의 규칙에 위배된다는 것이다.

          하지만 이러한 몇가지 문제점들을 해결하고 API 가로채기의 대부분의 목적을 달성할 수 있도록 하는 세련된 방법이 있다. 만약 관심이 있다면 [12] Detours implementation를 참조하기 바란다.

        4. Spying by a debugger(디버거를 이용한 스파이)
          An alternative to hooking API functions is to place a debugging breakpoint into the target function. However there are several drawbacks for this method. The major issue with this approach is that debugging exceptions suspend all application threads. It requires also a debugger process that will handle this exception. Another problem is caused by the fact that when the debugger terminates, the debugger is automatically shut down by Windows.

          API 함수를 후킹하는 또다른 방법은 디버깅 멈춤점을 목표로 하는 함수에 위치시키는 것이다. 하지만 이 방법에는 몇가지 단점들이 있다. 이 방식의 가장 큰 문제는 디버깅 예외가 모든 어플리케이션 쓰레드를 대기시킨다는 것이다. 이것은 또한 예외를 조작할 디버거 프로세스를 필요로 한다. 또다른 문제는 디버거가 종료할 때 윈도우즈가 자동으로 디버거를 끝낸다는 사실에 기인한다.(???)

          [역자주] 이 부분 역시 의미를 잘 모르겠고 내용 자체가 이 글의 주제를 벗어나기 때문에 대강 해석하였습니다.
        5. Spying by altering of the Import Address Table(임포트 주소 테이블 수정을 이용한 스파이)
          This technique was originally published by Matt Pietrek and than elaborated by Jeffrey Ritcher ([2] "API Hooking by Manipulating a Module's Import Section") and John Robbins ([4] "Hooking Imported Functions"). It is very robust, simple and quite easy to implement. It also meets most of the requirements of a hooking framework that targets Windows NT/2K and 9x operating systems. The concept of this technique relies on the elegant structure of the Portable Executable (PE) Windows file format. To understand how this method works, you should be familiar with some of the basics behind PE file format, which is an extension of Common Object File Format (COFF). Matt Pietrek reveals the PE format in details in his wonderful articles - [6] "Peering Inside the PE.", and [13a/b] "An In-Depth Look into the Win32 PE file format". I will give you a brief overview of the PE specification, just enough to get the idea of hooking by manipulation of the Import Address Table.

          이 기술은 Matt Pietrek이 처음 발표하였고 그후에 Jeffrey Ritcher ([2] "API Hooking by Manipulating a Module's Import Section") 와 John Robbins ([4] "Hooking Imported Functions")에 의해 다듬어졌다. 이 방법 매우 견실하며 단순하고 구현하기 상당히 쉬운 방법이다. 또한 NT/2k와 9x 운영체제를 모두 지원하는 후킹 프레임웍의 요구사항의 대부분을 만족시킬 수 있다. 이 기술의 개념은 PE(Portable Executable) 윈도우즈 파일 포맷의 우아한 구조에 의존한다. 이 방법이 어떻게 적용되는가를 이해하려면 Common Object File Format(COFF)의 확장 형태인 PE 파일 포맷에 대한 기본 지식에 친숙해져야 한다. Matt Pietrek은 그의 멋진 글인 [6] "Peering Inside the PE." 와 [13a/b] "An In-Depth Look into the Win32 PE file format"에서 PE 포맷의 베일을 벗겼다. PE 특성의 전반적인 설명만으로도 임포트 주소 테이블을 조작하여 후킹을 구현하는 아이디어를 얻을 수 있다.

          In general an PE binary file is organized, so that it has all code and data sections in a layout that conform to the virtual memory representation of an executable. PE file format is composed of several logical sections. Each of them maintains specific type of data and addresses particular needs of the OS loader.

          일반적으로 PE 이진 파일이 생성되면 실행시의 가상 메모리 구조를 따르는 형태의 코드와 데이터 섹션을 갖게 된다. PE 파일 포맷은 몇가지 논리적인 섹션으로 구성된다. 그것들 각각은 특정 유형의 데이터를 유지하고 OS 로더에게 특별한 요구를 지시한다.(???)

          The section .idata, I would like to focus your attention on, contains information about Import Address Table. This part of the PE structure is particularly very crucial for building a spy program based on altering IAT.
          Each executable that conforms with PE format has layout roughly described by the figure below.


             

          .idata 섹션은 특별히 관심을 기울여야 하는데 이것은 임포트 주소 테이블(IAT)에 관한 정보를 담고 있다. PE 구조의 이 부분은 IAT를 변경을 기반으로 하는 스파이 프로그램을 작성하는데 매우 중요하다.
          아래의 그림은 PE 포맷의 실행 파일 구조를 개략적으로 나타내고 있다.

          Figure 3


             


             
             

          The program loader is responsible for loading an application along with all its linked DLLs into the memory. Since the address where each DLL is loaded into, cannot be known in advance, the loader is not able to determine the actual address of each imported function. The loader must perform some extra work to ensure that the program will call successfully each imported function. But going through each executable image in the memory and fixing up the addresses of all imported functions one by one would take unreasonable amount of processing time and cause huge performance degradation. So, how does the loader resolves this challenge? The key point is that each call to an imported function must be dispatched to the same address, where the function code resides into the memory. Each call to an imported function is in fact an indirect call, routed through IAT by an indirect JMP instruction. The benefit of this design is that the loader doesn't have to search through the whole image of the file. The solution appears to be quite simple - it just fixes-up the addresses of all imports inside the IAT. Here is an example of a snapshot PE File structure of a simple Win32 Application, taken with the help of the [8] PEView utility. As you can see TestApp import table contains two imported by GDI32.DLL function -TextOutA() and GetStockObject().

          프로그램 로더는 어플리케이션을 로드하면서 어플리케이션에 링크된 DLL들을 함께 메모리에 로드한다. 각각의 DLL이 로드되는 주소는 미리 알 수 없기 때문에 로더는 임포트된 각각의 함수들의 실제 주소를 알지 못한다. 로더는 프로그램이 임포트된 함수를 성공적으로 호출할 수 있도록 별도의 작업을 수행하여야만 한다. 하지만 메모리 상의 실행 이미지 각각을 훝으면서 모든 임포트된 함수의 주소를 하나하나 수정하는 것은 과도한 처리 시간을 요구하고 엄청난 성능 저하를 유발한다. 그렇다면 로더는 이러한 문제를 어떻게 해결할까? 중요한 사실은 임포트된 함수에 대한 각각의 호출이 메모리 상에서 함수 코드가 위치하는 동일한 주소로 전달되어야만 한다는 것이다. 임포트된 함수에 대한 각각의 호출은 사실상 IAT를 거쳐 간접 JMP 명령을 통하는 간접적인 호출이다. 이러한 디자인의 이점은 로더가 파일의 모든 이미지를 훝지 않아도 된다는 것이다. 해결책이 약간 단순해 보인다. 단지 IAT 내부의 모든 임포트 주소를 수정하기만 하는 것이다. 아래에 간단한 Win32 어플리케이션의 PE 파일 구조의 형태를 [8] PEView utility를 사용하여 보여주는 예가 있다. TestApp 임포트 테이블이 GDI32.DLL의 2개 함수, TextOutA()GetStockObject()를 포함하는 것을 확인할 수 있다.

          Figure 4


             


              Actually the hooking process of an imported function is not that complex as
              it looks at first sight. In a nutshell an interception system that uses
              IAT patching has to discover the location that holds the address of imported
              function and replace it with the address of an user supplied function by
              overwriting it. An important requirement is that the newly provided function
              must have exactly the same signature as the original one. Here are the logical
              steps of a replacing cycle:
             
          • Locate the import section from the IAT of each loaded by the process DLL module as well as the process itself
          • Find the IMAGE_IMPORT_DESCRIPTOR chunk of the DLL that exports that function. Practically speaking, usually we search this entry by the name of the DLL
          • Locate the IMAGE_THUNK_DATA which holds the original address of the imported function
          • Replace the function address with the user supplied one

               

             

          임포트된 함수를 후킹하는 과정은 처음 보았을 때 느끼는 것처럼 복잡하지 않다. 간단히 말하면 IAT를 수정하는 후킹 시스템은 임포트된 함수의 주소를 가지고 있는 위치를 찾아 사용자 정의 함수의 주소로 덮어써서 바꿔 주는 것이다. 이 과정에서 중요한 요구 사항은 새로 제공하는 함수가 기존의 함수와 동일한 형태이어야 한다는 것이다. 아래에 교체 싸이클의 논리적 단계를 설명하였다.

          • 프로세스와 프로세스가 로드한 DLL 모듈의 각각의 IAT에서 임포트 섹션을 찾는다.
          • DLL에서 함수를 익스포트하는 IMAGE_IMPORT_DESCRIPTOR 청크를 찾는다. 실제로는 이 엔트리를 DLL의 이름으로 찾는다.
          • 임포트된 함수의 원래 주소를 가지고 있는 IMAGE_THUNK_DATA를 찾는다.
          • 사용자 정의 함수의 주소로 함수의 주소를 바꾼다.

          By changing the address of the imported function inside the IAT, we ensure that all calls to the hooked function will be re-routed to the function interceptor.

          IAT 내부의 임포트된 함수의 주소를 변경함으로서 후킹된 함수에 대한 호출은 새로운 함수로 연결되게 된다.

          Replacing the pointer inside the IAT is that .idata section doesn't necessarily have to be a writable section. This requires that we must ensure that .idata section can be modified. This task can be accomplished by using VirtualProtect() API.

          IAT 내부의 포인터를 바꾸기 위해서 .idata 섹션이 반드시 쓰기 가능할 필요는 없다..idata 섹션이 수정 가능하다는 것을 확신하는 것이 필요하다. 이 작업은VirtualProtect() API를 사용하여 수행할 수 있다.

          Another issue that deserves attention is related to the GetProcAddress() API behavior on Windows 9x system. When an application calls this API outside the debugger it returns a pointer to the function. However if you call this function within from the debugger it actually returns different address than it would when the call is made outside the debugger. It is caused by the fact that that inside the debugger each call to GetProcAddress() returns a wrapper to the real pointer. Returned by GetProcAddress() value points to PUSHinstruction followed by the actual address. This means that on Windows 9x when we loop through the thunks, we must check whether the address of examined function is a PUSHinstruction (0x68 on x86 platforms) and accordingly get the proper value of the address function.

          관심을 가져야 하는 또다른 문제점은 윈도우즈9x에서 GetProcAddress() API의 동작과 관련이 있다. 어플리케이션이 이 API를 디버거 외부에서 호출하면 이 API는 함수에 대한 포인터를 반환한다. 하지만 디버거 내에서 이 함수를 호출하면 디버거 외부에서 호출할 때 반환하는 주소와 다른 값을 반환한다. 이러한 현상은 디버거 내에서의GetProcAddress() 호출이 실제 포인터를 변환(wrapper)해서 반환하기 때문에 발생한다. GetProcAddress()가 반환하는 주소값은 PUSH 명령과 실제 주소가 나오는 위치를 가르킨다. 이것은 윈도우즈 9x에서는 청크를 순회할 때 반드시 검사한 함수의 주소가 PUSH명령 (0x68 on x86 platforms)인가를 체크하여 주소 함수의 적합한 값을 얻어야 한다는 것을 의미한다.

          Windows 9x doesn't implement copy-on-write, thus operating system attempts to keep away the debuggers from stepping into functions above the 2-GB frontier. That is the reason why GetProcAddress() returns a debug thunk instead of the actual address. John Robbins discusses this problem in [4] "Hooking Imported Functions".

          윈도우즈 9x는 copy-on-write를 지원하지 않으므로 운영체제는 디버거가 2-GB 한계 상단의 함수에 접근하지 못하도록 만든다.

          [역자주] copy-on-write는 두개의 프로세스가 동일한 자원을 읽기 용도로만 사용한다면 자원을 공유하여 사용하다가 하나의 프로세스가 자원에 대해 쓰기 시도를 하면 자원의 복사본을 만들어서 사용하는 것을 의미합니다. 아마도 성능 향상을 위해 운영체제가 채택하는 기술로 생각되며 "쓰기 위에 복사하기"가 아니라 "쓰면 복사한다"로 이해하면 됩니다.
          이것이 GetProcAddress()가 실제 주소 대신 디버그 청크를 반환하는 이유이다. John Robbins는 이 문제에 대하여 [4] "Hooking Imported Functions".에서 다루었다.

        [역자주] 여기까지의 내용을 요약해 보면 다음과 같습니다.

        1. API 후킹을 위해서는 기본적으로 서버 프로그램과 드라이버 DLL이 필요하다.
        2. 서버 프로그램은 DLL을 다른 프로세스에 침투시키는 역할을 한다.
        3. 드라이버 DLL은 프로세스 내의 API 호출을 가로채는 역할을 한다.
        4. 침투시키는 방법은 여러 가지가 있지만 윈도우즈 메시지 후크를 사용하는 방법과 CreateRemoteThread를 사용하는 방법이 제일 유리하다.
        5. API 호출을 가로채는 방법도 여러 가지가 있지만 IAT를 수정하는 방법이 제일 유리하다.
        6. 모든 OS를 지원하려면 서버는 메시지 후크를 이용하는 방법을 사용하고 드라이버는 IAT를 수정하는 방법을 채택해야 한다. (뒤에 나오겠지만 CreateRemoteThread를 이용하는 방법은 생각보다 훨씬 복잡합니다.)

        Figuring out when to inject the hook DLL(후킹 DLL 침투 과정의 이해)

        That section reveals some challenges that are faced by developers when the selected injection mechanism is not part of the operating system's functionality. For example, performing the injection is not your concern when you use built-in Windows Hooks in order to implant a DLL. It is an OS's responsibility to force each of those running processes that meet the requirements for this particular hook, to load the DLL [18]. In fact Windows keeps track of all newly launched processes and forces them to load the hook DLL. Managing injection through registry is quite similar to Windows Hooks. The biggest advantage of all those "built-in" methods is that they come as part of the OS.

        지금까지의 섹션에서 선택한 침투 메카니즘이 운영체제가 제공하는 기능이 아닌 경우 개발자들이 직면하게 되는 몇가지 문제점들에 대해 설명하였다. 예를 들면, DLL을 주입시키기 위해 운영체제가 제공하는 윈도우즈 후크를 사용한다면 침투를 수행하는 것은 관심의 대상이 아니다. 특정 후크의 조건에 부합하는 실행 프로세스가 DLL을 로드[18]하도록 하는 것은 운영체제의 몫이다. 사실상 윈도우즈 새로 적재된 모든 프로세스를 추적하고 프로세스들이 후킹 DLL을 로드하도록 강제한다. 레지스트리를 통한 침투 관리는 윈도우즈 후크와 약간 유사하다. 운영체제가 제공하는 모든 방법들의 가장 큰 장점은 운영체제의 일부분으로서 제공된다는 것이다.

        Unlike the discussed above implanting techniques, to inject by CreateRemoteThread() requires maintenance of all currently running processes. If the injecting is made not on time, this can cause the Hook System to miss some of the calls it claims as intercepted. It is crucial that the Hook Server application implements a smart mechanism for receiving notifications each time when a new process starts or shuts down. One of the suggested methods in this case, is to intercept CreateProcess() API family functions and monitor all their invocations. Thus when an user supplied function is called, it can call the original CreateProcess() with dwCreationFlags OR-ed with CREATE_SUSPENDED flag. This means that the primary thread of the targeted application will be in suspended state, and the Hook Server will have the opportunity to inject the DLL by hand-coded machine instructions and resume the application using ResumeThread() API. For more details you might refer to [2] "Injecting Code withCreateProcess()".

        상기의 침투 기술과 달리 CreateRemoteThread()를 이용하는 침투는 현재 실행 중인 모든 프로세스에 대한 관리를 요구한다. 만일 침투가 적절한 때에 이루어지지 않는다면 후크 시스템이 가로채기로 지정한 호출의 일부를 수행하지 못할 수가 있다. 후킹 서버 어플리케이션이 새로운 프로세스가 시작되거나 종료할 때마다 통보를 받을 수 있도록 세련된 메카니즘을 구현하는 것은 매우 중요하다. 이러한 경우 제안되는 방법 중의 하나가 CreateProcess() API 패밀리의 함수를 가로채서 감시하는 것이다. 그리고 후킹된 사용자 정의 함수가 호출될 때 원본 CreateProcess() 함수를 dwCreationFlagsCREATE_SUSPENDED 플래그를 OR 연산하여 호출한다. 이것은 목표로 하는 어플리케이션의 프라이머리 쓰레드를 대기 상태로 하여 후크 서버가 DLL을 침투시키도록 하고 ResumeThread() API로 어플리케이션을 기동시키는 것을 의미한다. 보다 자세한 정보를 원한다면 레퍼런스의 [2] "Injecting Code withCreateProcess()"를 참조하라.

        The second method of detecting process execution, is based on implementing a simple device driver. It offers the greatest flexibility and deserves even more attention. Windows NT/2K provides a special function PsSetCreateProcessNotifyRoutine() exported by NTOSKRNL. This function allows adding a callback function, that is called whenever a process is created or deleted. For more details see [11] and [15] from the reference section.


        프로세스의 실행을 감지하는 두번째 방법은 간단한 디바이스 드라이버를 구현하는 것이다. 이 방법은 가장 유연하고 큰 관심을 가질 만하다. 윈도우즈 NT/2K는 NTOKKRNL에서 익스포트된PsSetCreateProcessNotifyRoutine()라는 특별한 함수를 제공한다. 이 함수는 프로세스의 생성이나 소멸 시에 호출되는 콜백 함수를 추가하도록 해준다. 보다 자세한 내용은 레퍼런스의 [11]과 [15]를 참조하라.

        Enumerating processes and modules(프로세스와 모듈을 나열하기)

        Sometimes we would prefer to use injecting of the DLL by CreateRemoteThread() API, especially when the system runs under NT/2K. In this case when the Hook Server is started it must enumerate all active processes and inject the DLL into their address spaces. Windows 9x and Windows 2K provide a built-in implementation (i.e. implemented by Kernel32.dll) of Tool Help Library. On the other hand Windows NT uses for the same purpose PSAPI library. We need a way to allow the Hook Server to run and then to detect dynamically which process "helper" is available. Thus the system can determine which the supported library is, and accordingly to use the appropriate APIs.

        때때로 CreateRemoteThread() API를 이용하여 DLL을 침투시키는 방법이 선호된다. 특히 시스템이 NT/2K인 경우에 그러하다. 이 경우, 후크 서버가 시작될 때 모든 활성 프로세스를 나열하고 각각의 프로세스의 주소 공간에 DLL을 침투시켜야 한다. 윈도우즈 9x와 2K는 Tool Help Library의 내장 구현(Kernel32.dll로 구현된)을 제공한다. 윈도우즈 NT에서는 PSAPI 라이브러리를 같은 목적으로 사용할 수 있다. 그러므로 후크 서버는 실행된 후 어떤 프로세스 헬퍼 라이브러리를 사용할 수 있지를 판단하여 적절한 API들을 사용할 수 있도록 만들어져야 한다.

        I will present an object-oriented architecture that implements a simple framework for retrieving processes and modules under NT/2K and 9x [16]. The design of my classes allows extending the framework according to your specific needs. The implementation itself is pretty straightforward.

        이제부터 NT/2K와 9x [16] 환경에서 프로세스와 모듈을 추출하는 간단한 프레임웍에 대한 객체 지향 구조에 대해 설명하겠다. 이 클래스들의 디자인은 특정 요구 사항에 맞춰 확장이 용하도록 되어있다. 구현 자체는 매우 수월하다.

        CTaskManager implements the system's processor. It is responsible for creating an instance of a specific library handler (i.e. CPsapiHandler or CToolhelpHandler) that is able to employ the correct process information provider library (i.e. PSAPI or ToolHelp32 respectively). CTaskManager is in charge of creating and marinating a container object that keeps a list with all currently active processes. After instantiating of the CTaskManager object the application calls Populate() method. It forces enumerating of all processes and DLL libraries and storing them into a hierarchy kept byCTaskManager's member m_pProcesses.

        Following UML diagram shows the class relationships of this subsystem:


        CTaskManager는 시스템의 프로세서를 담당한다. 이 클래스는 운영체제가 제공하는 라이브러리((i.e. PSAPI or ToolHelp32 respectively)를 취사선택하여 특정 라이브러리 핸들러(CPsapiHandler orCToolhelpHandler)의 인스턴스를 생성하는 역할을 한다. CTaskManager는 현재 활성화된 모든 프로세스의 리스트를 유지하는 컨테이너 객체의 생성을 관리한다. CTaskManager 객체가 생성된 후에는 어플리케이션은 Populate() 메소드를 호출할 수 있다. 이 메소드는 모든 프로세스와 DLL 라이브러리를 나열하고 그 정보를 CTaskManager의 멤버 변수인 m_pProcesses에 계층적으로 저장한다.

        아래의 UML 다이어그램은 이러한 서브 시스템의 클래스 관계를 보여준다.


         

        Figure 5


        It is important to highlight the fact that NT's Kernel32.dll doesn't implement any of the ToolHelp32 functions. Therefore we must link them explicitly, using runtime dynamic linking. If we use static linking the code will fail to load on NT, regardless whether or not the application has attempted to execute any of those functions. For more details see my article "Single interface for enumerating processes and modules under NT and Win9x/2K.".


        NT의 Kernel32.dll이 ToolHelp32 함수의 어떤 것도 구현하지 않는다는 것은 매우 중요한 사실이다. 그러므로 실행시 동적 링크를 이용하여 명시적으로 DLL들을 링크하여야 한다. 만일 정적 링크를 사용한다면 어플리케이션이 그 함수들을 사용하는가에 무관하게 그 코드는 NT에서 로드에 실패할 것이다. 보다 자세한 내용은 "Single interface for enumerating processes and modules under NT and Win9x/2K."을 참조하기 바란다.

        Requirements of the Hook Tool System(후크 툴 시스템의 요구 사항)

        Now that I've made a brief introduction to the various concepts of the hooking process it's time to determine the basic requirements and explore the design of a particular hooking system. These are some of the issues addressed by the Hook Tool System:

        지금까지 후킹 프로세스의 다양한 개념들을 간략하게 설명하였다. 이제부터는 기본 요구 사항을 결정하고 후킹 시스템을 설계하는 것을 연구해 보겠다. 다음의 사항들은 후크 툴 시스템에서 제기되는 이슈들이다:

        • Provide a user-level hooking system for spying any Win32 API functions imported by name
        • Provide the abilities to inject hook driver into all running processes by Windows hooks as well as CreateRemoteThread() API. The framework should offer an ability to set this up by an INI file
        • Employ an interception mechanism based on the altering Import Address Table
        • Present an object-oriented reusable and extensible layered architecture
        • Offer an efficient and scalable mechanism for hooking API functions
        • Meet performance requirements
        • Provide a reliable communication mechanism for transferring data between the driver and the server
        • Implement custom supplied versions of TextOutA/W() and ExitProcess() API functions
        • Log events to a file
        • The system is implemented for x86 machines running Windows 9x, Me, NT or Windows 2K operating system
        • 이름으로 임포트된 어떤 Win32 API 함수도 후킹할 수 있는 사용자 레벨 후킹 시스템을 제공한다.
        • CreateRemoteThread() API뿐 아니라 윈도우즈 후크를 사용하여 모든 실행 프로세스에 후크 드라이버를 침투시킬 수 있도록 한다. 프렉임웍은 이것을 INI 파일로 설정할 수 있어야 한다.
        • 임포트 주소 테이블을 변경하는 것에 기초한 가로채기 메카니즘을 사용한다.
        • 객체 지향적인 재사용 가능하고 확장성 있는 계층 구조를 사용한다.
        • API 함수를 후킹하는 효율적이고 단계적인 메카니즘을 제공한다.
        • 성능적인 요구 사항을 충족시킨다.
        • 드라이버와 서버 간의 데이터 전송에 신뢰할 수 있는 교환 메카니즘을 제공한다.
        • TextOutA/W()ExitProcess() API 함수에 대한 사용자 정의 버전을 구현한다.
        • 이벤트를 파일에 기록한다.
        • 시스템은 윈도우즈 9x, Me, NT or 윈도우즈 2K를 운영체제로 하는 x86 머신에 대해 구현한다.

        Design and implementation(설계와 구현)

        This part of the article discusses the key components of the framework and how do they interact each other. This outfit is capable to capture any kind of WINAPI imported by name functions.

        이 섹션에서는 프레임웍의 주요 컴포넌트와 서로 간의 상호 작용에 대해 살펴 보겠다. 이 시스템은 이름으로 임포트되는 어떠한 종류의 WINAPI 함수도 가로챌 수가 있다.

        Before I outline the system's design, I would like to focus your attention on several methods for injecting and hooking.

        시스템의 설계를 요점을 설명하기 전에 침투와 후킹의 여러 방법들에 관심을 기울이기 바란다.

        First and foremost, it is necessary to select an implanting method that will meet the requirements for injecting the DLL driver into all processes. So I designed an abstract approach with two injecting techniques, each of them applied accordingly to the settings in the INI file and the type of the operating system (i.e. NT/2K or 9x). They are - System-wide Windows Hooks and CreateRemoteThread()method. The sample framework offers the ability to inject the DLL on NT/2K by Windows Hooks as well as to implant by CreateRemoteThread() means. This can be determined by an option in the INI file that holds all settings of the system.

        무엇보다 먼저 DLL 드라이버를 모든 프로세스에 침투시키는 요구 사항을 충족하는 주입 방법을 선택하는 것이 필요하다. 그래서 INI 파일의 설정과 운영체제(i.e. NT/2K or 9x)의 종류에 따라 적용할 2개의 침투 기술을 가지고 추상적인 접근을 설계했다. 그것은 시스템 전역 윈도우즈 후크와CreateRemoteThread()이다. 예제 프레임웍은 CreateRemoteThread() 함수를 사용해서 주입할 수 있을 뿐 아니라 NT/2K에서 윈도우즈 후크를 사용하여 DLL을 침투시킬 수도 있는 능력을 제공한다. 어떠한 것을 사용할 것인가는 시스템의 모든 설정을 가지고 있는 INI 파일의 설정에 따라 결정된다.

        Another crucial moment is the choice of the hooking mechanism. Not surprisingly, I decided to apply altering IAT as an extremely robust method for Win32 API spying.

        또다른 중요한 결정은 후킹 메카니즘을 선택하는 것이다. 당연히 Win32 API를 후킹하는 매우 견실한 방법인 IAT 변경을 적용하기로 결정하였다.

        To achieve desired goals I designed a simple framework composed of the following components and files:

        • TestApp.exe - a simple Win32 test application that just outputs a text using TextOut() API. The purpose of this app is to show how it gets hooked up.
        • HookSrv.exe - control program
        • HookTool .DLL - spy library implemented as Win32 DLL
        • HookTool.ini - a configuration file
        • NTProcDrv.sys - a tiny Windows NT/2K kernel-mode driver for monitoring process creation and termination. This component is optional and addresses the problem with detection of process execution under NT based systems only.

        요구되는 목표를 달성하기 위해 다음의 콤포넌트와 파일로 구성되는 단순한 프레임웍을 설계하였다:

        • TestApp.exe - TextOut() API를 사용하여 텍스트를 출력하는 단순한 Win32 테스트 어플리케이션. 이 어플리케이션의 목적은 어떻게 후킹이 되는가를 보여주는 것이다.
        • HookSrv.exe - 제어 프로그램.
        • HookTool .DLL - Win32 DLL로 구현된 스파이 라이브러리.
        • HookTool.ini - 설정 파일.
        • NTProcDrv.sys - 프로세스의 생성과 소멸을 감시하는 작은 윈도우즈 NT/2K 커널 모드 드라이버. 이 컴포넌트는 선택 사항이며 NT 시스템에서만 프로세스의 실행을 감지하여 문제점을 찾아낸다.
          [역자주] 이 드라이버를 컴파일하기 위해서는 윈도우즈 DDK(Device Driver Kit)가 설치되어 있어야 한다. DDK는 무료가 아니므로 MSDN 가입자가 아니면 마이크로소프트에서 다운로드 받을 수가 없다. 하지만 이 드라이버는 모니터하는 용도의 선택 사항이므로 후킹 예제를 테스트하기 위해 반드시 컴파일이 필요하지는 않다.

        HookSrv is a simple control program. Its main role is to load the HookTool.DLL and then to activate the spying engine. After loading the DLL, the Hook Server calls InstallHook() function and passes a handle to a hidden windows where the DLL should post all messages to.

        HookSrv는 단순한 제어 프로그램이다. 이것의 주요 임무는 HookTool.DLL을 로드하여 스파이 엔진을 활성화시키는 것이다. DLL을 로드한 후에 후크 서버는 InstallHook() 함수를 호출하고 DLL이 모든 메시지를 전달해야 하는 숨겨진 윈도우에 핸들을 넘겨준다.

        HookTool.DLL is the hook driver and the heart of presented spying system. It implements the actual interceptor and provides three user supplied functions TextOutA/W() and ExitProcess() functions.

        HookTool.DLL은 후크 드라이버이고 스파이 시스템의 핵심이다. 이것은 실질적인 가로채기를 구현하고TextOutA/W()ExitProcess()에 대한 3개의 사용자 정의 함수를 제공한다.

        Although the article emphasizes on Windows internals and there is no need for it to be object-oriented, I decided to encapsulate related activities in reusable C++ classes. This approach provides more flexibility and enables the system to be extended. It also benefits developers with the ability to use individual classes outside this project.

        이 글에서 윈도우즈 내부적인 측면에 대해 강조하였고 반드시 시스템이 객체 지향이어야 할 이유는 없지만 상호 간의 동작을 재사용 가능한 C++ 클래스에 캡슐화하기로 결정하였다. 이러한 접근은 더많은 유연성을 제공하고 시스템이 확장 가능하도록 만들어 준다. 또한 개발자가 다른 프로젝트에서도 개별적인 클래스를 사용할 수 있다는 장점이 있다.

        Following UML class diagram illustrates the relationships between set of classes used in HookTool.DLL's implementation.


        아래의 UML 다이어그램은 HookTool.DLL의 구현에 사용되는 일련의 클래스들의 관계를 나타낸다.

        [역자주] 저자는 이 글의 목표를 범용적인 프레임웍의 설계에 두었고 클래스 설계에 싱클턴 패턴이나 템플릿 메쏘드 패턴 같은 디자인 패턴을 많이 적용하였기 때문에 객체 지향 설계나 디자인 패턴에 대한 지식이 없다면 구조나 흐름을 이해하기가 상당히 어렵습니다. 기회가 된다면 이 예제를 조금 단순화시킨 프로그램을 만들어서 올리도록 하겠습니다.

        Figure 6

         

        In this section of the article I would like to draw your attention to the class design of the HookTool.DLL. Assigning responsibilities to the classes is an important part of the development process. Each of the presented classes wraps up a specific functionality and represents a particular logical entity.

        이 섹션에서는 HookTool.DLL의 클래스 설계에 관심을 가지기 바란다. 클래스에 역할을 할당하는 것은 개발 과정에서 매우 중요한 부분이다. 제시된 클래스들 각각은 특별한 기능을 감추고 있고 특별한 논리적 개체로 표현된다.

        CModuleScope is the main doorway of the system. It is implemented using "Singleton" pattern and works in a thread-safe manner. Its constructor accepts 3 pointers to the data declared in the shared segment, that will be used by all processes. By this means the values of those system-wide variables can be maintained very easily inside the class, keeping the rule for encapsulation.

        CModuleScope는 시스템의 주 출입구이다. 이 클래스는 싱글턴 패턴을 사용하여 구현되었고 thread-safe한 방식으로 동작한다. 이 클래스의 생성자는 공유 세그먼트에 선언되어 있는 3개의 데이터에 대한 포인터를 매개변수로 넘겨받고 이 데이터는 모든 프로세스에서 사용하게 된다. 이것은 시스템 전역 변수의 값이 클래스 내부에서 매우 쉽게 관리된다는 것을 의미하고 캡슐화의 규칙을 유지하게 된다.

        When an application loads the HookTool library, the DLL creates one instance of CModuleScope on receiving DLL_PROCESS_ATTACH notification. This step just initializes the only instance ofCModuleScope. An important piece of the CModuleScope object construction is the creation of an appropriate injector object. The decision which injector to use will be made after parsing the HookTool.ini file and determining the value of UseWindowsHook parameter under [Scope] section. In case that the system is running under Windows 9x, the value of this parameter won't be examined by the system, because Window 9x doesn't support injecting by remote threads.

        어떤 어플리케이션이 HookTool 라이브러리를 로드할 때 DLL은 DLL_PROCESS_ATTACH 통지를 받고CModuleScope 객체를 하나 생성한다. CModuleScope 객체 생성의 중요한 부분은 적합한 침투 객체를 생성하는 것이다. 어떤 침투 클래스를 사용할 것인가는 HookTool.ini 파일을 읽어 [Scope] 섹션의UseWindowsHook 항목의 값을 확인한 후에 결정된다. 시스템이 윈도우즈 9x에서 실행되는 경우에는 리모트 쓰레드를 사용하는 침투가 지원되지 않으므로 이 항목은 시스템이 무시한다.

        After instantiating of the main processor object, a call to ManageModuleEnlistment() method will be made. Here is a simplified version of its implementation:


        주 처리 객체가 생성된 후에 ManageModuleEnlistment() 메소드를 호출하게 된다. 아래에 이 메소드의 구현을 단순화한 소스가 있다.

        // Called on DLL_PROCESS_ATTACH DLL notification BOOL CModuleScope::ManageModuleEnlistment() { BOOL bResult = FALSE; // Check if it is the hook server  if (FALSE == *m_pbHookInstalled) { // Set the flag, thus we will know that the server has been installed *m_pbHookInstalled = TRUE; // and return success error code bResult = TRUE; } // and any other process should be examined whether it should be // hooked up by the DLL else { bResult = m_pInjector->IsProcessForHooking(m_szProcessName); if (bResult) InitializeHookManagement(); } return bResult; } 

        The implementation of the method ManageModuleEnlistment() is straightforward and examines whether the call has been made by the Hook Server, inspecting the value m_pbHookInstalled points to. If an invocation has been initiated by the Hook Server, it just sets up indirectly the flagsg_bHookInstalled to TRUE. It tells that the Hook Server has been started.

        ManageModuleEnlistment() 메소드의 구현은 간단하다. m_pbHookInstalled가 가르키는 값을 검사하여 후크 서버에 의한 호출인가를 확인한다. 만일 후크 서버에 의한 실행이라면 단순히sg_bHookInstalled를 TRUE로 설정한다. 이것은 후크 서버가 이미 시작되었음을 나타낸다.

        The next action taken by the Hook Server is to activate the engine through a single call toInstallHook() DLL exported function. Actually its call is delegated to a method of CModuleScope -InstallHookMethod(). The main purpose of this function is to force targeted for hooking processes to load or unload the HookTool.DLL.

        후크 서버가 취하는 다음 행동은 DLL의 익스포트된 함수인 InstallHook()를 한번 호출하여 엔진을 활성화시키는 것이다.

         // Activate/Deactivate hooking engine BOOL CModuleScope::InstallHookMethod(BOOL bActivate, HWND hWndServer) { BOOL bResult; if (bActivate) { *m_phwndServer = hWndServer; bResult = m_pInjector->InjectModuleIntoAllProcesses(); } else { m_pInjector->EjectModuleFromAllProcesses(); *m_phwndServer = NULL; bResult = TRUE; } return bResult; } 

        HookTool.DLL provides two mechanisms for self injecting into the address space of an external process - one that uses Windows Hooks and another that employs injecting of DLL by CreateRemoteThread()API. The architecture of the system defines an abstract class CInjector that exposes pure virtual functions for injecting and ejecting DLL. The classes CWinHookInjector and CRemThreadInjectorinherit from the same base - CInjector class. However they provide different realization of the pure virtual methods InjectModuleIntoAllProcesses() and EjectModuleFromAllProcesses(), defined in CInjector interface.

        HookTool.DLL은 다른 프로세스의 주소 공간에 스스로 침투하는 2가지의 메카니즘 -윈도우즈 후크를 이용하는 하는 방법과 CreateRemoteThread() API를 이용하여 DLL을 침투시키는 방법- 을 제공한다. 시스템의 구조는 DLL을 주입하고 뽑아내는 순수 가상 함수를 가지는 추상 클래스 CInjector를 정의한다. CWinHookInjectorCRemThreadInjector는 같은 부모 클래스 CInjector를 상속한다. 하지만 이들 자식 클래스들은 CInjector 인터페이스에 정의된 순수 가상 메소드인 CWinHookInjectorCRemThreadInjector를 다른 방식으로 구현한다.

        CWinHookInjector class implements Windows Hooks injecting mechanism. It installs a filter function by the following call


        CWinHookInjector 클래스는 윈도우즈 후크를 이용하는 침투 메카니즘으로 구현된다. 이 클래스는 아래의 소스와 같이 필터 함수를 설치한다.

        // Inject the DLL into all running processes BOOL CWinHookInjector::InjectModuleIntoAllProcesses() { *sm_pHook = ::SetWindowsHookEx( WH_GETMESSAGE, (HOOKPROC)(GetMsgProc), ModuleFromAddress(GetMsgProc), 0 ); return (NULL != *sm_pHook); } 

        As you can see it makes a request to the system for registering WH_GETMESSAGE hook. The server executes this method only once. The last parameter of SetWindowsHookEx() is 0, becauseGetMsgProc() is designed to operate as a system-wide hook. The callback function will be invoked by the system each time when a window is about to process a particular message. It is interesting that we have to provide a nearly dummy implementation of the GetMsgProc() callback, since we don't intend to monitor the message processing. We supply this implementation only in order to get free injection mechanism provided by the operating system.

        보는 바와 같이 이 소스는 시스템에 WH_GETMESSAGE 후크를 등록하도록 요청한다. 서버는 이 메소드를 단한번 실행한다. GetMsgProc()는 시스템 전역 후크로 동작하도록 설계되었으므로SetWindowsHookEx() 함수의 마지막 매개변수는 0이다. 콜백 함수는 윈도우가 특별한 메시지를 처리하려고 할 때 마다 실행된다. 메시지 처리 과정을 감시하는 것을 의도하지 않는다면 GetMsgProc() 콜백 함수를 거의 아무 것도 하지 않게 구현하여 제공하여야 한다는 것은 흥미로운 일이다. 운영체제가 제공하는 쉬운 침투 메카니즘을 이용하기 위해서는 이렇게만 구현하면 된다.

        After making the call to SetWindowsHookEx(), OS checks whether the DLL (i.e. HookTool.DLL) that exports GetMsgProc() has been already mapped in all GUI processes. If the DLL hasn't been loaded yet, Windows forces those GUI processes to map it. An interesting fact is, that a system-wide hook DLL should not return FALSE in its DllMain(). That's because the operating system validates DllMain()'s return value and keeps trying to load this DLL until its DllMain() finally returns TRUE.

        SetWindowsHookEx() 함수를 호출하면 OS는 GetMsgProc()를 익스포트하고 있는 DLL(i.e. HookTool.DLL)이 모든 GUI 프로세스에 이미 매핑이 되어 있는가를 검사한다. DLL이 아직 로드되지 않았다면 윈도우즈는 GUI 프로세스가 DLL을 매핑하도록 명령한다. 흥미로운 사실은 시스템 전역 후크 DLL은 DllMain()에서 절대로 FALSE를 반환하지 않는다는 것이다. 이것은 운영체제가 DllMain()의 반환값을 검사하여 DllMain()TRUE를 반환할 때까지 로드를 시도하기 때문이다.

        A quite different approach is demonstrated by the CRemThreadInjector class. Here the implementation is based on injecting the DLL using remote threads. CRemThreadInjector extends the maintenance of the Windows processes by providing means for receiving notifications of process creation and termination. It holds an instance of CNtInjectorThread class that observes the process execution.CNtInjectorThread object takes care for getting notifications from the kernel-mode driver. Thus each time when a process is created a call to CNtInjectorThread ::OnCreateProcess() is issued, accordingly when the process exits CNtInjectorThread ::OnTerminateProcess() is automatically called. Unlike the Windows Hooks, the method that relies on remote thread, requires manual injection each time when a new process is created. Monitoring process activities will provide us with a simple technique for alerting when a new process starts.

        CRemThreadInjector 클래스는 아주 다른 방식으로 접근한다. 이제부터는 리모트 쓰레드를 사용하여 DLL을 침투시키는 방식에 기초한 구현을 설명하겠다. CRemThreadInjector는 프로세스의 생성과 소멸에 관한 통지를 받는 방법을 이용하여 윈도우즈 프로세스의 관리를 확장시킨다. 이 클래스는 프로세스의 실행을 감시하는 CNtInjectorThread 클래스 객체를 멤버 변수로 가진다. CNtInjectorThread객체는 커널 모드 드라이버로부터 통지를 받는 것을 감시한다. 어떤 프로세스가 생성될 때 마다CNtInjectorThread ::OnCreateProcess() 함수가 호출되고 프로세스가 종료할 때CNtInjectorThread ::OnTerminateProcess() 함수가 호출된다. 윈도우즈 후크와 다르게 리모트 쓰레드에 의존하는 방식은 새로운 프로세스가 생성될 때 마다 침투 작업이 필요하다. 프로세스의 활동을 감시하는 것은 새로운 프로세스가 시작될 때 마다 변경 작업을 하는 간단한 방법을 제공한다.

        CNtDriverController class implements a wrapper around API functions for administering services and drivers. It is designed to handle the loading and unloading of the kernel-mode driver NTProcDrv.sys. Its implementation will be discussed later.

        CNtDriverController 클래스는 서비스와 드라이버를 관리하는 API 함수로 구현된다. 이 클래스는 커널 모드 드라이버 NTProcDrv.sys의 로드와 언로드를 조작하도록 설계되었다. 이것의 구현은 나중에 논의하겠다.

        After a successful injection of HookTool.DLL into a particular process, a call toManageModuleEnlistment() method is issued inside the DllMain(). Recall the method's implementation that I described earlier. It examines the shared variable sg_bHookInstalled through theCModuleScope 's member m_pbHookInstalled. Since the server's initialization had already set the value of sg_bHookInstalled to TRUE, the system checks whether this application must be hooked up and if so, it actually activates the spy engine for this particular process.

        어떤 특정 프로세스로 HookTool.DLL을 침투시키는 것이 성공하면 DllMain()에서ManageModuleEnlistment() 함수를 호출하게 된다. 위에서 설명한 이 메소드의 구현을 생각해 보자. 이 함수는 CModuleScope의 멤버 변수인 m_pbHookInstalled로 저장되는 공유하는 변수인sg_bHookInstalled를 검사한다. 서버의 초기화에서 이미 sg_bHookInstalled의 값을 TRUE로 설정하였으므로 시스템은 이 어플리케이션이 후크되었는가를 검사하고 그렇다면 이 프로세스에 스파이 엔진을 실질적으로 활성화시킨다.

        Turning the hacking engine on, takes place in the CModuleScope::InitializeHookManagement()'s implementation. The idea of this method is to install hooks for some vital functions as LoadLibrary()API family as well as GetProcAddress(). By this means we can monitor loading of DLLs after the initialization process. Each time when a new DLL is about to be mapped it is necessary to fix-up its import table, thus we ensure that the system won't miss any call to the captured function.

        후킹 엔진이 활성화되었으면 CModuleScope::InitializeHookManagement()의 구현이 실행된다. 이 방식에서는 GetProcAddress()LoadLibrary() API 계열의 함수에 후크를 설치한다. 이것은 초기화 과정 후에 DLL의 로드를 감시할 수 있다는 것을 의미한다. 어떤 새로운 DLL이 매핑될 때 마다 그것의 임포트 테이블을 수정하는 작업이 필요하고 그렇게 함으로서 시스템은 가로챈 함수의 호출을 놓치지 않게 된다.

        At the end of the InitializeHookManagement() method we provide initializations for the function we actually want to spy on.

        InitializeHookManagement() 메소드의 끝부분에서 실제로 스파이하기를 원하는 함수의 초기화를 하게 된다.

        Since the sample code demonstrates capturing of more than one user supplied functions, we must provide a single implementation for each individual hooked function. This means that using this approach you cannot just change the addresses inside IAT of the different imported functions to point to a single "generic" interception function. The spying function needs to know which function this call comes to. It is also crucial that the signature of the interception routine must be exactly the same as the original WINAPI function prototype, otherwise the stack will be corrupted. For example CModuleScopeimplements three static methods MyTextOutA(),MyTextOutW() and MyExitProcess(). Once the HookTool.DLL is loaded into the address space of a process and the spying engine is activated, each time when a call to the original TextOutA() is issued, CModuleScope:: MyTextOutA() gets called instead.

        예제 코드가 여러 개의 사용자 정의 함수로 가로채는 것을 보여주므로 후크 함수 각각을 처리할 수 있는 하나의 공통된 함수로 구현하여야 한다. 이것은 이러한 방식을 사용해서는 서로 다른 임포트된 함수의 IAT 내부의 주소들을 하나의 가로채기 함수를 가리키도록 바꿀 수는 없다는 것을 의미한다.

        [역자주] 여러 개의 함수를 후킹하여야 하므로 후킹하는 루틴을 하나의 함수로 만들어서 사용한다는 뜻입니다. 실제 소스에서는 BOOL CApiHookMgr::HookImport(PCSTR pszCalleeModName, PCSTR pszFuncName, PROC pfnHook)로 구현하여 아래와 같이 사용합니다.
        HookImport("Kernel32.dll", "LoadLibraryA", (PROC) CApiHookMgr::MyLoadLibraryA);
        HookImport("Kernel32.dll", "LoadLibraryW", (PROC) CApiHookMgr::MyLoadLibraryW);
        HookImport("Kernel32.dll", "LoadLibraryExA", (PROC) CApiHookMgr::MyLoadLibraryExA);

        스파이 함수는 호출하는 함수에 대해 알아야만 한다. 또한 가로채기 루틴의 형태가 원본 WINAPI 함수의 원형과 일치해야 한다는 것은 매우 중요하다. 그렇지 않으면 스택이 손상될 것이다. 예를 들면CModuleScopeMyTextOutA(),MyTextOutW(),MyExitProcess(), 3개의 전역 함수를 구현하고 있다. HookTool.DLL이 어떤 프로세스의 주소 공간에 로드되고 스파이 엔진이 활성화 되면 원본TextOutA()의 호출이 요청될 때 마다 CModuleScope:: MyTextOutA()가 대신 호출된다.



        Proposed design of the spying engine itself is quite efficient and offers great flexibility. However, it is suitable mostly for scenarios where the set of functions for interception is known in advance and their number is limited.

        스파이 엔진 자체의 설계는 매우 효율적이고 상당한 유연성을 제공한다. 하지만 가로채려는 함수를 미리 알 수 있는 경우에 적합한데 그러한 함수의 수는 한정되어 있다.

        If you want to add new hooks to the system you simply declare and implement the interception function as I did with MyTextOutA/W() and MyExitProcess(). Then you have to register it in the way shown by InitializeHookManagement() implementation.

        시스템에 새로운 후크를 추가하려면 샘플의 MyTextOutA/W()MyExitProcess()처럼 단순히 가로채기 함수를 선언하고 구현하기만 하면 된다. 그리고 나서 InitializeHookManagement()의 구현에서 처럼 그 함수를 등록하여야 한다.

        Intercepting and tracing process execution is a very useful mechanism for implementing systems that require manipulations of external processes. Notifying interested parties upon starting of a new processes is a classic problem of developing process monitoring systems and system-wide hooks. The Win32 API provides a set of great libraries (PSAPI and ToolHelp [16]) that allow you to enumerate processes currently running in the system. Although these APIs are extremely powerful they don't permit you to get notifications when a new process starts or ends up. Luckily, NT/2K provides a set of APIs, documented in Windows DDK documentation as "Process Structure Routines" exported by NTOSKRNL. One of these APIs PsSetCreateProcessNotifyRoutine() offers the ability to register system-wide callback function which is called by OS each time when a new process starts, exits or has been terminated. The mentioned API can be employed as a simple way to for tracking down processes simply by implementing a NT kernel-mode driver and a user mode Win32 control application. The role of the driver is to detect process execution and notify the control program about these events. The implementation of the Windows process's observer NTProcDrv provides a minimal set of functionalities required for process monitoring under NT based systems. For more details see articles [11] and [15]. The code of the driver can be located in the NTProcDrv.c file. Since the user mode implementation installs and uninstalls the driver dynamically the currently logged-on user must have administrator privileges. Otherwise you won't be able to install the driver and it will disturb the process of monitoring. A way around is to manually install the driver as an administrator or run HookSrv.exe using offered by Windows 2K "Run as different user" option.  

        프로세스의 실행을 가로채고 추적하는 것은 외부 프로세스를 조작하는 시스템을 구현하는 것에 매우 유용한 메카니즘이다. 관심이 있는 새로운 프로세스의 시작을 통지하는 것은 프로세스 감시 시스템과 시스템 전역 후크를 개발할 때 제기되는 고전적인 문제이다. Win32 API는 현재 시스템에서 실행되고 있는 프로세스를 나열할 수 있도록 하는 강력한 라이브러리(PSAPI와 ToolHelp [16])를 제공한다. 이 API들이 매우 강력하지만 새로운 프로세스가 생성되거나 소멸하는 것을 통지하지는 못한다. 다행스럽게도 NT/2K는 윈도우즈 DDK 문서에 설명되어 있고 NTOSKRNL에 익스포트되어 있는 "Process Structure Routines"라는 일련의 API들을 제공한다. 이 API 중의 하나인PsSetCreateProcessNotifyRoutine()은 새로운 프로세스가 생성되거나 종료, 강제 종료될 때마다 OS가 호출하는 시스템 전역 콜백 함수를 등록할 수 있도록 해준다. 이 API는 NT 커널 모드 드라이버와 사용자 모드 Win32 제어 어플리케이션을 구현하여 쉽게 프로세스를 추적할 수 있는 방법으로 사용될 수 있다. 드라이버의 역할은 프로세스의 실행을 감지하여 이 이벤트를 제어 프로그램에 통지하는 역할을 한다. 윈도우즈 프로세스 감시자인 NTProcDrv는 NT 환경에서 프로세스 감시를 수행하기에 필요한 최소한의 기능들을 제공하도록 구현되었다. 보다 자세한 내용은 레퍼런스의 [11]과 [15]의 글을 참조하기 바란다. 드라이버의 코드는 NTProcDrv.c 파일에 있다. 사용자 모드 프로그램이 드라이버를 동적으로 설치, 삭제를 하므로 현재 로그온한 사용자는 관리자 권한을 가져야 한다. 그렇지 않으면 드라이버를 설치할 수 없고 프로세스를 감시할 수 없을 것이다. 다른 방법으로는 관리자로서 드라이버를 수동으로 설치하거나 윈도우즈 2K에서 제공하는 "다른 사용자로 실행하기" 옵션으로 HookSrv.exe를 실행하는 것이 있다.

        Last but not least, the provided tools can be administered by simply changing the settings of an INI file (i.e. HookTool.ini). This file determines whether to use Windows hooks (for 9x and NT/2K) orCreateRemoteThread() (only under NT/2K) for injecting. It also offers a way to specify which process must be hooked up and which shouldn't be intercepted. If you would like to monitor the process there is an option (Enabled) under section [Trace] that allows to log system activities. This option allows you to report rich error information using the methods exposed by CLogFile class. In fact ClogFile provides thread-safe implementation and you don't have to take care about synchronization issues related to accessing shared system resources (i.e. the log file). For more details see CLogFile and content of HookTool.ini file.

        마지막이지만 사소하지 않은 것이 제공되는 도구들이 단순히 INI 파일(i.e. HookTool.ini)의 설정을 바꿈으로서 관리된다는 것이다. 이 파일은 침투를 위해 윈도우즈 후크(9x,NT/2K)를 사용할 것인가 아니면 CreateRemoteThread()(NT/2K에서만)를 사용할 것인가를 결정한다. 또한 어떤 프로세스를 후크하고 어떤 프로세스는 후크하지 않을 것인가를 설정할 수도 있다. 만일 프로세스를 감시하기를 원한다면 [Trace] 섹션의 (Enabled)의 값을 세팅하여 시스템의 활동을 기록할 수도 있다. 이 옵션은 CLogFile 클래스의 메소드를 사용하여 상세한 오류 정보를 기록한다. 실제로 CLogFile 클래스는 thread-safe하게 구현되었고 공유 시스템 자원(즉 로그 파일) 접근과 관련된 동기화 문제에 신경쓰지 않아도 된다. 보다 자세한 내용은 CLogFile과 HookTool.ini 파일을 참조하기 바란다.

        Sample code(예제 코드)

        The project compiles with VC6++ SP4 and requires Platform SDK. In a production Windows NT environment you need to provide PSAPI.DLL in order to use provided CTaskManager implementation.

        이 프로젝트는 VC6++ SP4에서 컴파일되고 플랫폼 SDK를 필요로 한다. 윈도우즈 NT 환경에서 실행되는 경우 CTaskManager의 구현을 사용하기 위해 PSAPI.DLL이 필요하다.

        Before you run the sample code make sure that all the settings in HookTool.ini file have been set according to your specific needs.

        예제 코드를 실행하기 전에 특정 요구 사항에 맞게 HookTool.ini 파일이 제대로 설정되었는가를 확인해야 한다.

        For those that will like the lower-level stuff and are interested in further development of the kernel-mode driver NTProcDrv code, they must install Windows DDK.

        저수준의 방법을 선호하고 커널 모드 드라이버 NTProcDrv의 코드를 개발할 계획이라면 윈도우즈 DDK가 요구된다.

        Out of the scope(이글의 범위를 벗어나는 것들)

        For the sake of simplicity these are some of the subjects I intentionally left out of the scope of this article:

        • Monitoring Native API calls
        • A driver for monitoring process execution on Windows 9x systems.
        • UNICODE support, although you can still hook UNICODE imported APIs

        단순하게 하기 위해 아래의 주제들은 이글에서 다루지 않았다:

        • 네이티브 API 호출의 감시
        • 윈도우즈 9x 시스템에서 프로세스 실행을 감시하는 드라이버
        • UNICODE 지원

        Conclusion(결론)

        This article by far doesn't provide a complete guide for the unlimited API hooking subject and without any doubt it misses some details. However I tried to fit in this few pages just enough important information that might help those who are interested in user mode Win32 API spying.

        이 글은 절대로 무제한의 API 후킹에 대한 완벽한 가이드가 아니며 의심할 바 없이 일부 자세한 내용들이 빠져있다. 하지만 몇 페이지의 글에 사용자 모드 Win32 API 후킹에 관심이 있는 사람들이 중요한 정보를 주기에 충분하도록 노력하였다.

        References

        [1] "Windows 95 System Programming Secrets", Matt Pietrek
        [2] "Programming Application for MS Windows" , Jeffrey Richter 
        [3]
        "Windows NT System-Call Hooking" , Mark Russinovich and Bryce Cogswell, Dr.Dobb's Journal January 1997
        [4]
        "Debugging applications" , John Robbins 
        [5]
        "Undocumented Windows 2000 Secrets" , Sven Schreiber 
        [6]
        "Peering Inside the PE: A Tour of the Win32 Portable Executable File Format" by Matt Pietrek, March 1994
        [7] MSDN Knowledge base Q197571
        [8]
        PEview Version 0.67 , Wayne J. Radburn
        [9] "Load Your 32-bit DLL into Another Process's Address Space Using INJLIB" MSJ May 1994
        [10]
        "Programming Windows Security" , Keith Brown
        [11]
        "Detecting Windows NT/2K process execution" Ivo Ivanov, 2002
        [12]
        "Detours" Galen Hunt and Doug Brubacher 
        [13a]
        "An In-Depth Look into the Win32 PE file format" , part 1, Matt Pietrek, MSJ February 2002
        [13b]
        "An In-Depth Look into the Win32 PE file format" , part 2, Matt Pietrek, MSJ March 2002
        [14]
        "Inside MS Windows 2000 Third Edition" , David Solomon and Mark Russinovich 
        [15]
        "Nerditorium", James Finnegan, MSJ January 1999 
        [16]
        "Single interface for enumerating processes and modules under NT and Win9x/2K." , Ivo Ivanov, 2001
        [17]
        "Undocumented Windows NT" , Prasad Dabak, Sandeep Phadke and Milind Borate
        [18]
        Platform SDK: Windows User Interface, Hooks