• Jueves 18 de Agosto de 2022, 18:58

Mostrar Mensajes

Esta sección te permite ver todos los posts escritos por este usuario. Ten en cuenta que sólo puedes ver los posts escritos en zonas a las que tienes acceso en este momento.


Mensajes - L3andro

Páginas: [1]
1
ASM (Ensamblador) / Consulta Sobre Programacion De Dll En Asm
« en: Lunes 17 de Diciembre de 2007, 18:00 »
Hola a todos, bueno quisiera consultarles lo siguiente, estoy intentando trabajar con una DLL programada en ASM, tengo algunas cuantas dudas sobre el tema, las cuales seguramente no sean muy complicadas de contestar.

 Bueno el codigo Fuente completo hasta ahora de la DLL es el siguiente:

Código: Text
  1.  
  2. ;EasyCodeName=Module1,1
  3. .386
  4. .Model flat, StdCall
  5. Option CaseMap:none
  6. Include  \masm32\include\windows.inc
  7. Include  \masm32\include\user32.inc
  8. Include  \masm32\include\kernel32.inc
  9. Include  \masm32\include\masm32.inc
  10. IncludeLib  \masm32\lib\user32.lib
  11. IncludeLib  \masm32\lib\kernel32.lib
  12. IncludeLib  \masm32\lib\masm32.lib
  13. Include  \masm32\macros\MACROS.ASM
  14.  
  15. .Const
  16. MEMSIZE Equ 175535
  17. LittleBuffer Equ 10H
  18. GSAuthKey1 Equ 00BE2329H
  19. GSAuthKey2 Equ 0AED66CE1H
  20. GSAuthKey3 Equ 0F1499052H
  21. GSAuthKey4 Equ 0EBE9BBF1H
  22. GSAuthKey5 Equ 0A6B3H
  23. GSAuthKey6 Equ 0DBH
  24. .Data
  25. ItemKor DB "..\data\lang\Kor\item(Kor).txt", 0
  26. ItemVTM DB "..\data\lang\vtm\item(Vtm).txt", 0
  27. SkillKor DB "..\data\lang\Kor\skill(Kor).txt", 0
  28. SkillVTM DB "..\data\lang\vtm\skill(Vtm).txt", 0
  29. QuestKor DB "..\data\lang\Kor\Quest(Kor).txt", 0
  30. QuestVTM DB "..\data\lang\Vtm\Quest(Vtm).txt", 0
  31. CheckSum DB "..\data\lang\Kor\CheckSum.dat", 0
  32. Monster DB "..\data\Monster.txt", 0
  33. Gate DB "..\data\gate.txt", 0
  34. MonsterBase DB "..\data\MonsterSetBase.txt", 0
  35. Shop0 DB "..\data\Shop0.txt", 0
  36. Shop1 DB "..\data\Shop1.txt", 0
  37. Shop2 DB "..\data\Shop2.txt", 0
  38. Shop3 DB "..\data\Shop3.txt", 0
  39. Shop4 DB "..\data\Shop4.txt", 0
  40. Shop5 DB "..\data\Shop5.txt", 0
  41. Shop6 DB "..\data\Shop6.txt", 0
  42. Shop7 DB "..\data\Shop7.txt", 0
  43. Shop8 DB "..\data\Shop8.txt", 0
  44. Shop9 DB "..\data\Shop9.txt", 0
  45. Shop10 DB "..\data\Shop10.txt", 0
  46. Shop11 DB "..\data\Shop11.txt", 0
  47. Shop12 DB "..\data\Shop12.txt", 0
  48. MoveReqKor DB "..\data\lang\Kor\movereq(kor).txt", 0
  49. MoveReqVTM DB "..\data\lang\Vtm\movereq(Vtm).txt", 0
  50. ItemSetOption DB "..\data\lang\Kor\itemsetoption(Kor).txt", 0
  51. ItemSetType DB "..\data\lang\Kor\itemsettype(Kor).txt", 0
  52. CommonLoc DB "..\data\lang\Kor\CommonLoc.cfg", 0
  53. GameServerInfo DB "GameServerInfo", 0
  54. ClientVersion DB "ClientExeVersion", 0
  55. ClientSerial DB "ClientExeSerial", 0
  56. ServerName DD LittleBuffer Dup(0)
  57. VersionServer DD LittleBuffer Dup(0)
  58. ClientVersionReturn DD LittleBuffer Dup(0)
  59. ClientSerialReturn DD LittleBuffer Dup(0)
  60. AGGSOffset DD ?
  61. AGSOffset2 DD ?
  62. FirstTime DD ?
  63. .Data?
  64. hFile HANDLE ?
  65. hMemory HANDLE ?
  66. pMemory DWord ?
  67. SizeReadWrite DWord ?
  68. .Code
  69. DllEntry Proc hInstDLL:HINSTANCE, reason:DWord, reserved1:DWord
  70.  Mov Eax, TRUE
  71.  Ret
  72. DllEntry EndP
  73.  
  74. AGSetInfo Proc
  75.  Mov Eax, DWord Ptr Ss:[Ebp + 18H]
  76.  Mov Ecx, DWord Ptr Ss:[Ebp + 14H]
  77.  Mov Edx, DWord Ptr Ss:[Ebp + 0CH]
  78.  Mov Ebx, DWord Ptr Ss:[Ebp + 20H]
  79.  Mov ServerName, Eax
  80.  Mov VersionServer, Ecx
  81.  Mov AGGSOffset, Edx
  82.  Mov AGSOffset2, Ebx
  83.  Xor Eax, Eax
  84.  Ret
  85. AGSetInfo EndP
  86.  
  87. AGGetKey Proc
  88.  Mov Edx, GSAuthKey1
  89.  Mov Eax, DWord Ptr Ss:[Ebp + 8]
  90.  Mov DWord Ptr Ds:[Eax], Edx
  91.  Mov Edx, GSAuthKey2
  92.  Mov DWord Ptr Ds:[Eax + 4], Edx
  93.  Mov Edx, GSAuthKey3
  94.  Mov DWord Ptr Ds:[Eax + 8], Edx
  95.  Mov Edx, GSAuthKey4
  96.  Mov DWord Ptr Ds:[Eax + 0CH], Edx
  97.  Mov Cx, GSAuthKey5
  98.  Mov Word Ptr Ds:[Eax + 10H], Cx
  99.  Mov Dl, GSAuthKey6
  100.  Mov Byte Ptr Ds:[Eax + 12H], Dl
  101.  Xor Eax, Eax
  102.  Ret
  103. AGGetKey EndP
  104.  
  105. AGRequestData Proc
  106.  Local Number:DWord
  107.  Cmp FirstTime, 0
  108.  Jnz DeleteBuffer
  109.  Mov FirstTime, 1
  110.  Jmp SwitchNumbers
  111. DeleteBuffer:
  112.  Invoke CloseHandle, hFile
  113.  Invoke GlobalUnlock, pMemory
  114.  Invoke GlobalFree, hMemory
  115. SwitchNumbers:
  116.  Mov Ecx, DWord Ptr Ss:[Ebp + 0CH]
  117.  Mov Number, Ecx
  118.  Switch Number
  119. Case 0
  120.  Mov Eax, Offset ItemKor
  121. Case 1
  122.  Mov Eax, Offset ItemVTM
  123. Case 2
  124.  Mov Eax, Offset SkillKor
  125. Case 3
  126.  Mov Eax, Offset SkillVTM
  127. Case 4
  128.  Mov Eax, Offset QuestKor
  129. Case 5
  130.  Mov Eax, Offset QuestVTM
  131. Case 6
  132.  Mov Eax, Offset CheckSum
  133. Case 7
  134.  Mov Eax, Offset Monster
  135. Case 8
  136.  Mov Eax, Offset Gate
  137. Case 9
  138.  Mov Eax, Offset MonsterBase
  139. Case 0BH
  140.  Mov Eax, Offset Shop0
  141. Case 0CH
  142.  Mov Eax, Offset Shop1
  143. Case 0DH
  144.  Mov Eax, Offset Shop2
  145. Case 0EH
  146.  Mov Eax, Offset Shop3
  147. Case 0FH
  148.  Mov Eax, Offset Shop4
  149. Case 10H
  150.  Mov Eax, Offset Shop5
  151. Case 11H
  152.  Mov Eax, Offset Shop6
  153. Case 12H
  154.  Mov Eax, Offset Shop7
  155. Case 13H
  156.  Mov Eax, Offset Shop8
  157. Case 14H
  158.  Mov Eax, Offset Shop9
  159. Case 15H
  160.  Mov Eax, Offset Shop10
  161. Case 16H
  162.  Mov Eax, Offset Shop11
  163. Case 17H
  164.  Mov Eax, Offset Shop12
  165. Case 18H
  166.  Mov Eax, Offset MoveReqKor
  167. Case 1AH
  168.  Mov Eax, Offset ItemSetOption
  169. Case 1CH
  170.  Mov Eax, Offset ItemSetType
  171. EndSw
  172. LoadFile:
  173.  Invoke CreateFile, Eax, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL
  174.  Mov hFile, Eax
  175.  Invoke GlobalAlloc, GMEM_MOVEABLE Or GMEM_ZEROINIT, MEMSIZE
  176.  Mov hMemory, Eax
  177.  Invoke GlobalLock, hMemory
  178.  Mov pMemory, Eax
  179.  Invoke ReadFile, hFile, pMemory, MEMSIZE - 1, Addr SizeReadWrite, NULL
  180.  Xor Eax, Eax
  181.  Ret
  182. AGRequestData EndP
  183.  
  184. AGGetDataBufferSize Proc
  185.  Mov Eax, SizeReadWrite
  186.  Ret
  187. AGGetDataBufferSize EndP
  188.  
  189. AGGetDataBuffer Proc
  190.  Mov Eax, pMemory
  191.  Ret
  192. AGGetDataBuffer EndP
  193.  
  194. AGGetClientVersion Proc
  195. Invoke GetPrivateProfileString, Addr GameServerInfo, Addr ClientVersion, NULL, Addr ClientVersionReturn, 14H, Addr CommonLoc
  196. Invoke GetPrivateProfileString, Addr GameServerInfo, Addr ClientSerial, NULL, Addr ClientSerialReturn, 14H, Addr CommonLoc
  197. Mov Eax, DWord Ptr Ds:[ClientVersionReturn]
  198. Mov Ecx, DWord Ptr Ds:[ClientVersionReturn + 4]
  199. Mov Edx, DWord Ptr Ss:[Ebp + 8]
  200. Mov DWord Ptr Ds:[Edx], Eax
  201. Mov DWord Ptr Ds:[Edx + 4], Ecx
  202. Mov Eax, DWord Ptr Ds:[ClientSerialReturn]
  203. Mov Ecx, DWord Ptr Ds:[ClientSerialReturn + 4]
  204. Mov Edx, DWord Ptr Ss:[Ebp + 0CH]
  205. Mov DWord Ptr Ds:[Edx], Eax
  206. Mov DWord Ptr Ds:[Edx + 4], Ecx
  207. Mov Eax, DWord Ptr Ds:[ClientSerialReturn + 8]
  208. Mov Ecx, DWord Ptr Ds:[ClientSerialReturn + 0CH]
  209. Mov DWord Ptr Ds:[Edx + 8], Eax
  210. Mov DWord Ptr Ds:[Edx + 0CH], Ecx
  211. Mov Eax, DWord Ptr Ds:[ClientSerialReturn + 10H]
  212. Mov DWord Ptr Ds:[Edx + 10H], Eax
  213. Xor Eax, Eax
  214. Ret
  215. AGGetClientVersion EndP
  216.  
  217. End DllEntry
  218.  
  219.  

Asi como esta, funciona bien... Ahora mi consulta es la siguiente, me decidi a agregarle algunas funciones mas de configuracion, añadiendo un .ini - y quisiera ver si esto esta bien y si de estarlo hay alguna forma de optimizar el codigo si pueden asesorarme, o corregirme de estar mal.

 Lo que agrego seria lo siguiente.

Dentro de .Data añado esto:

Código: Text
  1.  
  2. .Data
  3.  
  4. IsGlobalChatBuff DB 1 Dup(0)
  5. GChatLevelBuff DB 4 Dup(0)
  6. GChatMoneyBuff DB 4 Dup(0)
  7.  
  8. Sections DB "Config", 0
  9. IniFileName DB "./Config.ini" , 0
  10.  
  11.  


Y posteriormente creo un nuevo Proc de la siguiente manera:

Código: Text
  1.  
  2. LoadConfig Proc
  3.   Invoke GetPrivateProfileInt, Addr Sections, Addr IsGlobalChat, 0, Addr IniFileName
  4.   Mov DWord Ptr Ds:[IsGlobalChatBuff], Eax
  5.   Invoke GetPrivateProfileInt, Addr Sections, Addr GChatLevel, 50, Addr IniFileName
  6.   Mov DWord Ptr Ds:[GChatLevelBuff], Eax
  7.   Invoke GetPrivateProfileInt, Addr Sections, Addr GChatMoney, 10000, Addr IniFileName
  8.   Mov DWord Ptr Ds:[GChatMoneyBuff], Eax
  9.   Retn
  10. LoadConfig EndP
  11.  
  12.  


Las opciones son muchisimas mas, pero en resumen la idea es esa, y esto quedaria de la siguiente manera:

Código: Text
  1.  
  2.  
  3. .386
  4. .Model flat, StdCall
  5. Option CaseMap:none
  6. Include  \masm32\include\windows.inc
  7. Include  \masm32\include\user32.inc
  8. Include  \masm32\include\kernel32.inc
  9. Include  \masm32\include\masm32.inc
  10. IncludeLib  \masm32\lib\user32.lib
  11. IncludeLib  \masm32\lib\kernel32.lib
  12. IncludeLib  \masm32\lib\masm32.lib
  13. Include  \masm32\macros\MACROS.ASM
  14.  
  15. .Const
  16. MEMSIZE Equ 175535
  17. LittleBuffer Equ 10H
  18. GSAuthKey1 Equ 00BE2329H
  19. GSAuthKey2 Equ 0AED66CE1H
  20. GSAuthKey3 Equ 0F1499052H
  21. GSAuthKey4 Equ 0EBE9BBF1H
  22. GSAuthKey5 Equ 0A6B3H
  23. GSAuthKey6 Equ 0DBH
  24. .Data
  25.  
  26. IsGlobalChatBuff DB 1 Dup(0)
  27. GChatLevelBuff DB 4 Dup(0)
  28. GChatMoneyBuff DB 4 Dup(0)
  29.  
  30. Sections DB "Config", 0
  31. IniFileName DB "./Config.ini" , 0
  32.  
  33. ItemKor DB "..\data\lang\Kor\item(Kor).txt", 0
  34. ItemVTM DB "..\data\lang\vtm\item(Vtm).txt", 0
  35. SkillKor DB "..\data\lang\Kor\skill(Kor).txt", 0
  36. SkillVTM DB "..\data\lang\vtm\skill(Vtm).txt", 0
  37. QuestKor DB "..\data\lang\Kor\Quest(Kor).txt", 0
  38. QuestVTM DB "..\data\lang\Vtm\Quest(Vtm).txt", 0
  39. CheckSum DB "..\data\lang\Kor\CheckSum.dat", 0
  40. Monster DB "..\data\Monster.txt", 0
  41. Gate DB "..\data\gate.txt", 0
  42. MonsterBase DB "..\data\MonsterSetBase.txt", 0
  43. Shop0 DB "..\data\Shop0.txt", 0
  44. Shop1 DB "..\data\Shop1.txt", 0
  45. Shop2 DB "..\data\Shop2.txt", 0
  46. Shop3 DB "..\data\Shop3.txt", 0
  47. Shop4 DB "..\data\Shop4.txt", 0
  48. Shop5 DB "..\data\Shop5.txt", 0
  49. Shop6 DB "..\data\Shop6.txt", 0
  50. Shop7 DB "..\data\Shop7.txt", 0
  51. Shop8 DB "..\data\Shop8.txt", 0
  52. Shop9 DB "..\data\Shop9.txt", 0
  53. Shop10 DB "..\data\Shop10.txt", 0
  54. Shop11 DB "..\data\Shop11.txt", 0
  55. Shop12 DB "..\data\Shop12.txt", 0
  56. MoveReqKor DB "..\data\lang\Kor\movereq(kor).txt", 0
  57. MoveReqVTM DB "..\data\lang\Vtm\movereq(Vtm).txt", 0
  58. ItemSetOption DB "..\data\lang\Kor\itemsetoption(Kor).txt", 0
  59. ItemSetType DB "..\data\lang\Kor\itemsettype(Kor).txt", 0
  60. CommonLoc DB "..\data\lang\Kor\CommonLoc.cfg", 0
  61. GameServerInfo DB "GameServerInfo", 0
  62. ClientVersion DB "ClientExeVersion", 0
  63. ClientSerial DB "ClientExeSerial", 0
  64. ServerName DD LittleBuffer Dup(0)
  65. VersionServer DD LittleBuffer Dup(0)
  66. ClientVersionReturn DD LittleBuffer Dup(0)
  67. ClientSerialReturn DD LittleBuffer Dup(0)
  68. AGGSOffset DD ?
  69. AGSOffset2 DD ?
  70. FirstTime DD ?
  71. .Data?
  72. hFile HANDLE ?
  73. hMemory HANDLE ?
  74. pMemory DWord ?
  75. SizeReadWrite DWord ?
  76. .Code
  77. DllEntry Proc hInstDLL:HINSTANCE, reason:DWord, reserved1:DWord
  78.  Mov Eax, TRUE
  79.  Ret
  80. DllEntry EndP
  81.  
  82. LoadConfig Proc
  83.   Invoke GetPrivateProfileInt, Addr Sections, Addr IsGlobalChat, 0, Addr IniFileName
  84.   Mov DWord Ptr Ds:[IsGlobalChatBuff], Eax
  85.   Invoke GetPrivateProfileInt, Addr Sections, Addr GChatLevel, 50, Addr IniFileName
  86.   Mov DWord Ptr Ds:[GChatLevelBuff], Eax
  87.   Invoke GetPrivateProfileInt, Addr Sections, Addr GChatMoney, 10000, Addr IniFileName
  88.   Mov DWord Ptr Ds:[GChatMoneyBuff], Eax
  89.   Retn
  90. LoadConfig EndP
  91.  
  92. AGSetInfo Proc
  93.  Mov Eax, DWord Ptr Ss:[Ebp + 18H]
  94.  Mov Ecx, DWord Ptr Ss:[Ebp + 14H]
  95.  Mov Edx, DWord Ptr Ss:[Ebp + 0CH]
  96.  Mov Ebx, DWord Ptr Ss:[Ebp + 20H]
  97.  Mov ServerName, Eax
  98.  Mov VersionServer, Ecx
  99.  Mov AGGSOffset, Edx
  100.  Mov AGSOffset2, Ebx
  101.  Xor Eax, Eax
  102.  Ret
  103.  AGSetInfo
  104.  
  105. AGGetKey Proc
  106.  Mov Edx, GSAuthKey1
  107.  Mov Eax, DWord Ptr Ss:[Ebp + 8]
  108.  Mov DWord Ptr Ds:[Eax], Edx
  109.  Mov Edx, GSAuthKey2
  110.  Mov DWord Ptr Ds:[Eax + 4], Edx
  111.  Mov Edx, GSAuthKey3
  112.  Mov DWord Ptr Ds:[Eax + 8], Edx
  113.  Mov Edx, GSAuthKey4
  114.  Mov DWord Ptr Ds:[Eax + 0CH], Edx
  115.  Mov Cx, GSAuthKey5
  116.  Mov Word Ptr Ds:[Eax + 10H], Cx
  117.  Mov Dl, GSAuthKey6
  118.  Mov Byte Ptr Ds:[Eax + 12H], Dl
  119.  Xor Eax, Eax
  120.  Ret
  121. AGGetKey EndP
  122.  
  123. AGRequestData Proc
  124.  Local Number:DWord
  125.  Cmp FirstTime, 0
  126.  Jnz DeleteBuffer
  127.  Mov FirstTime, 1
  128.  Jmp SwitchNumbers
  129. DeleteBuffer:
  130.  Invoke CloseHandle, hFile
  131.  Invoke GlobalUnlock, pMemory
  132.  Invoke GlobalFree, hMemory
  133. SwitchNumbers:
  134.  Mov Ecx, DWord Ptr Ss:[Ebp + 0CH]
  135.  Mov Number, Ecx
  136.  Switch Number
  137. Case 0
  138.  Mov Eax, Offset ItemKor
  139. Case 1
  140.  Mov Eax, Offset ItemVTM
  141. Case 2
  142.  Mov Eax, Offset SkillKor
  143. Case 3
  144.  Mov Eax, Offset SkillVTM
  145. Case 4
  146.  Mov Eax, Offset QuestKor
  147. Case 5
  148.  Mov Eax, Offset QuestVTM
  149. Case 6
  150.  Mov Eax, Offset CheckSum
  151. Case 7
  152.  Mov Eax, Offset Monster
  153. Case 8
  154.  Mov Eax, Offset Gate
  155. Case 9
  156.  Mov Eax, Offset MonsterBase
  157. Case 0BH
  158.  Mov Eax, Offset Shop0
  159. Case 0CH
  160.  Mov Eax, Offset Shop1
  161. Case 0DH
  162.  Mov Eax, Offset Shop2
  163. Case 0EH
  164.  Mov Eax, Offset Shop3
  165. Case 0FH
  166.  Mov Eax, Offset Shop4
  167. Case 10H
  168.  Mov Eax, Offset Shop5
  169. Case 11H
  170.  Mov Eax, Offset Shop6
  171. Case 12H
  172.  Mov Eax, Offset Shop7
  173. Case 13H
  174.  Mov Eax, Offset Shop8
  175. Case 14H
  176.  Mov Eax, Offset Shop9
  177. Case 15H
  178.  Mov Eax, Offset Shop10
  179. Case 16H
  180.  Mov Eax, Offset Shop11
  181. Case 17H
  182.  Mov Eax, Offset Shop12
  183. Case 18H
  184.  Mov Eax, Offset MoveReqKor
  185. Case 1AH
  186.  Mov Eax, Offset ItemSetOption
  187. Case 1CH
  188.  Mov Eax, Offset ItemSetType
  189. EndSw
  190. LoadFile:
  191.  Invoke CreateFile, Eax, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL
  192.  Mov hFile, Eax
  193.  Invoke GlobalAlloc, GMEM_MOVEABLE Or GMEM_ZEROINIT, MEMSIZE
  194.  Mov hMemory, Eax
  195.  Invoke GlobalLock, hMemory
  196.  Mov pMemory, Eax
  197.  Invoke ReadFile, hFile, pMemory, MEMSIZE - 1, Addr SizeReadWrite, NULL
  198.  Xor Eax, Eax
  199.  Ret
  200. AGRequestData EndP
  201.  
  202. AGGetDataBufferSize Proc
  203.  Mov Eax, SizeReadWrite
  204.  Ret
  205. AGGetDataBufferSize EndP
  206.  
  207. AGGetDataBuffer Proc
  208.  Mov Eax, pMemory
  209.  Ret
  210. AGGetDataBuffer EndP
  211.  
  212. AGGetClientVersion Proc
  213. Invoke GetPrivateProfileString, Addr GameServerInfo, Addr ClientVersion, NULL, Addr ClientVersionReturn, 14H, Addr CommonLoc
  214. Invoke GetPrivateProfileString, Addr GameServerInfo, Addr ClientSerial, NULL, Addr ClientSerialReturn, 14H, Addr CommonLoc
  215. Mov Eax, DWord Ptr Ds:[ClientVersionReturn]
  216. Mov Ecx, DWord Ptr Ds:[ClientVersionReturn + 4]
  217. Mov Edx, DWord Ptr Ss:[Ebp + 8]
  218. Mov DWord Ptr Ds:[Edx], Eax
  219. Mov DWord Ptr Ds:[Edx + 4], Ecx
  220. Mov Eax, DWord Ptr Ds:[ClientSerialReturn]
  221. Mov Ecx, DWord Ptr Ds:[ClientSerialReturn + 4]
  222. Mov Edx, DWord Ptr Ss:[Ebp + 0CH]
  223. Mov DWord Ptr Ds:[Edx], Eax
  224. Mov DWord Ptr Ds:[Edx + 4], Ecx
  225. Mov Eax, DWord Ptr Ds:[ClientSerialReturn + 8]
  226. Mov Ecx, DWord Ptr Ds:[ClientSerialReturn + 0CH]
  227. Mov DWord Ptr Ds:[Edx + 8], Eax
  228. Mov DWord Ptr Ds:[Edx + 0CH], Ecx
  229. Mov Eax, DWord Ptr Ds:[ClientSerialReturn + 10H]
  230. Mov DWord Ptr Ds:[Edx + 10H], Eax
  231. Xor Eax, Eax
  232. Ret
  233. AGGetClientVersion EndP
  234.  
  235.  
  236. End DllEntry
  237.  
  238.  

 Bueno mi consulta es la nombrada, quisiera saber si los ultimos agregados como el del .ini para configuracion estan bien aplicados, y si hay alguna manera de optimizar el codigo.

Saludos y desde ya gracias.

2
Delphi / Re: Consulta - Como Utilizar "virtual Protec" ?
« en: Lunes 17 de Diciembre de 2007, 16:40 »
Cita de: "Eternal Idol"
No se puede utilizar una en lugar de otra ya que no hacen lo mismo.

A grosso modo OpenProcess obtiene un HANDLE a un proceso y VirtualProtect cambia la proteccion de la memoria especificada - sobre el proceso actual, para actuar sobre un tercero tenes que usar VirtualProtectEx -.

Documentacion:
OpenProcess.
VirtualProtect.
 Hola Eternal Idol, como siempre muchas gracias por despejar mis dudas.

 Saludos, y gracias nuevamente  :)

3
Delphi / Consulta - Como Utilizar "virtual Protec" ?
« en: Lunes 17 de Diciembre de 2007, 15:50 »
Buenos dias a todos, bueno mi consulta es la siguiente: Quisiera saber como utilizar en una DLL la Funcion Virtual Protect en lugar de OpenProcces, por ejemplo.

Código: Text
  1.  
  2. // Start Procedure (Loader)
  3. procedure InitDLL;stdcall;export;inline;
  4. begin
  5.   ProcessId:=OpenProcess(PROCESS_ALL_ACCESS, False,GetCurrentProcessId);
  6.   if(ProcessId<>0)then
  7.     begin
  8.         TCReward;
  9.         PotBug;
  10.         NoIDUser;
  11.     end;
  12. end;
  13.  
  14. {EXPORTS SECTION}
  15. exports
  16.   InitDLL;
  17.  
  18. begin
  19. end.  
  20.  
  21.  

 Como podría hacer para utilizar el VirtualProtect en lugar de OpenProcess ?
Desde y amuchas gracias, por cualquier ayuda que puedan brindarme.

4
ASM (Ensamblador) / Re: Consulta - Permiso De Escritura En Offset
« en: Lunes 3 de Septiembre de 2007, 17:29 »
Cita de: "Eternal Idol"
No es lo logico tener que modificar el PE a mano para solucionar este problema ... ¿De donde salio ese codigo y que pretende hacer?
 Hola Eternal Idol, bueno el codigo ese lo que hace es cargar una DLL con su respectivo Proc (DLL = DbDatos.dll - Proc de la DLL = msgbox), la aplicacion tiene una DLL Hookeada, ya que el EP de la aplicacion es el inicio de la carga de la dll y no el EP Real (en PUSH EBP) por lo cual la deduccion lo primero que hace la aplicacion es cargar la DLL y su Proc en el .exe al terminar la carga de la DLL y Proc los mueve a a otras direcciones de memoria para ser utilizados, el problema se halla en esa parte los offset a donde los mueve no pueden ser escritos por no tener permiso. Hacer que la aplicacion en cuestion pueda ser ejecutada sin ningun problema es en teoria y practica bastante sencillo ya que lo unico que deberia hacer es cambiar el Entry Point por el original y saltear el codigo en cuestion (Problematico) eso seria sencillo si presto atencion al codigo:

Código: Text
  1.  
  2. PUSH appz3.0068EF76                            &#59; /FileName = "DbDatos.dll"
  3. CALL DWORD PTR DS:[<&KERNEL32.LoadLibraryA>]      &#59; \LoadLibraryA
  4. MOV DWORD PTR DS:[68ED96],EAX                     &#59;  Mueve la Carga de la DLL al Offset 68ED96
  5. PUSH appz3.0068EF86                            &#59; /ProcNameOrOrdinal = "msgbox"
  6. PUSH EAX                                          &#59; |hModule
  7. CALL DWORD PTR DS:[<&KERNEL32.GetProcAddress>]    &#59; \GetProcAddress
  8. MOV DWORD PTR DS:[68ED9A],EAX                     &#59;  Mueve la Caraga del Proc al Offset 68ED9A
  9. CALL EAX
  10. JMP appz3.[B]005828E5 [/B]                            &#59;  Con este JMP Regresamos al EP!
  11.  
  12.  

 En ese codigo se ve que al terminar la carga de la DLL y Proc este mismo vuelve al EP original con la siguiente linea:
JMP appz3.005828E5                             ;  Con este JMP Regresamos al EP!
 Por lo cual de querer solucionar la carga de la Aplicacion podria cambiar el EP actual por ->005828E5 el tema es que de hacer eso y saltear el codigo en cuestion si bien la aplicacion funcionaria sin problemas (Lo he probado) la misma careceria de las funciones agregadas por la DLL, por eso mismo quisiera saber como convertir dichos Offset en Modo Write.

 Coincido plenamente con vos en que no es logico tener que modificar el PE a mano en este tipo de casos ya que la aplicacion deberia funcionar de por si, la aplicacion en cuestion es Free y OpenSource el problema se basa en quien halla agregado la DLL con funciones en cuestion ovbiamente no lo hiso desde el Source si no que por hooking ya que es ovbio al ver el codigo de la misma, el problema se basa en que la pagina web oficial del producto, en donde podian descargarse el Source y Aplicacion estan caidas desde aproximadamente 1 mes, por lo cual por otros lados han continuado el desarrollo, y hoy en dia me es un tanto complicado conseguir el source ya que el mismo asi como aplicacion pertenecian a un portal de desarrollo de China  :(  

 En fin, se que no es la mejor forma ni el mejor camino para solucionar el problema que tengo, pero si es la unica via disponible de la cual dispongo hoy en dia. Verdaderamente si bien comprendo sobre ASM (lo basico ya que estoy estudiando con e-books & e-learning) y tras varios intentos de conseguir el objetivo, me encuentro blockeado con esto tras ya varios intentos frustrados.

 Bueno Eternal Idol, espero puedas darme una mano orientandome con eso, se que probablemente no te paresca lo mejor, y creeme que para mi tampoco es el mejor camino pero me parece contrsuctivo no solo desde el punto de vista de que solucionaria mi problema, si no que tambien desde el lado de poder entender algo mas de todo esto.

Gracias nuevamente por tu tiempo y cualquier ayuda que puedas brindarme.

5
ASM (Ensamblador) / Consulta - Permiso De Escritura En Offset
« en: Domingo 2 de Septiembre de 2007, 06:07 »
Bueno tengo un problema con una aplicacion, el cual la verdad no estoy muy seguro como solucionar, y consta en que al ejecutarla esta se cierra automaticamente, al cargarla con un Debuguer como el Olly o WinDBG, y Ejecutarla desde el mismo, puedo ver que el problema se produce en las siguiente linea:

Código: Text
  1.  
  2. MOV DWORD PTR DS:[68ED96],EAX                      &#59;  Mueve la Carga de la DLL al Offset 68ED96
  3.  
  4.  

 como referencia pongo tambien el codigo completo sobre lo afectado:

Código: Text
  1.  
  2. PUSH appz3.0068EF76                             &#59; /FileName = "DbDatos.dll"
  3. CALL DWORD PTR DS:[<&KERNEL32.LoadLibraryA>]       &#59; \LoadLibraryA
  4. MOV DWORD PTR DS:[68ED96],EAX                      &#59;  Mueve la Carga de la DLL al Offset 68ED96
  5. PUSH appz3.0068EF86                             &#59; /ProcNameOrOrdinal = "msgbox"
  6. PUSH EAX                                           &#59; |hModule
  7. CALL DWORD PTR DS:[<&KERNEL32.GetProcAddress>]     &#59; \GetProcAddress
  8. MOV DWORD PTR DS:[68ED9A],EAX                      &#59;  Mueve la Caraga del Proc al Offset 68ED9A
  9. CALL EAX
  10. JMP appz3.005828E5                              &#59;  Con este JMP Regresamos al EP!
  11.  
  12.  

 Bueno ahi carga una dll en primer instancia, y luego con el "MOV EAX, DWORD PTR DS:[68ED9A]" la mueve a otra direccion para ser usada o almenos eso me parece a mi, y es justo alli donde se produce el error, El Offset a donde quiere moverla no tiene permiso de escritura por lo cual se produce una falla por que el offset 68ED9A no tiene permiso de escritura, y seguramente al reparar ese tambien deba hacerlo con el offset a donde se mueve para ser usado el msgbox (El Proc); mi pregunta seria, como puedo hacer que esos offset sean tengan permiso de escritura, supongo que deberia usar algun editor PE para conseguirlo, pero podrian explicarme cual es el camino y forma indicada de lograrlo? desde ya estoy muy agradecido.

chauchas :hola:

6
ASM (Ensamblador) / Re: [duda] Como Ver El Pid & Tid De Un Proceso
« en: Domingo 22 de Julio de 2007, 01:30 »
Cita de: "Eternal Idol"
Un proceso no tiene TID por obvias razones, un proceso si tiene cuanto menos un hilo y cada hilo tiene un TID.

Usa el Process Explorer.
Te haceguro que me aclaraste MUCHISIMO mas todo el panorama master. Muchisimas gracias por la ayuda, y por pasarme el Process Explorer.

Saludos master y gracias denuevo :D

7
ASM (Ensamblador) / [duda] Como Ver El Pid & Tid De Un Proceso
« en: Sábado 21 de Julio de 2007, 09:43 »
Buenas noches, me gustaria saber si alguien puede indicarme como hago para ver el PID y TID de un Proceso en mi ordenador, el PID puedo verlo desde el TaskManager o desde el Process Viewer el cual me muestra el PID de cada proceso en ejecucion en mi PC, pero como puedo hacer para llegar a saber cual es el Thread ID del Proceso?

 Desde ya muchas gracias muchachos.
Saludos.

8
Visual Basic 6.0 e inferiores / Armando Formularios Transparentes.
« en: Miércoles 18 de Julio de 2007, 17:21 »
Hola muchach@s, bueno este es mi primer post aqui en Solo Codigo, llegue hasta aqui por recomendacion de unos amigos que al ver que quiero introducirme un poco mas en ASM e ir aprendiendo me recomendaron este sitio. Para que mi primer post no sean preguntas quiero colaborar con esto quizas a alguien le sea de utilidad.

 A continuación veremos como podemos armar un formulario "invisible", esto podria tener varias utilidades pero eso ya dependera de la que ustedes quieran darle, por ejemplo podriamos dejar un text o un command volando, asi que bueno comenzemos.

Código: Text
  1.  
  2. Option Explicit
  3. 'Declaraciones de los diferentes tipos de regiones a crear
  4. Private Declare Function CreateRectRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
  5. Private Declare Function CreateEllipticRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
  6. Private Declare Function CreateRoundRectRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long, ByVal X3 As Long, ByVal Y3 As Long) As Long
  7. Private Declare Function CreatePolygonRgn Lib "gdi32" (lpPoint As POINTAPI, ByVal nCount As Long, ByVal nPolyFillMode As Long) As Long
  8. 'POINTAPI tipo requerido para CreatePolygonRgn
  9. Private Type POINTAPI
  10.         X As Long
  11.         Y As Long
  12. End Type
  13. 'Fija la region
  14. Private Declare Function SetWindowRgn Lib "user32" (ByVal hwnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long
  15. 'Combina la region
  16. Private Declare Function CombineRgn Lib "gdi32" (ByVal hDestRgn As Long, ByVal hSrcRgn1 As Long, ByVal hSrcRgn2 As Long, ByVal nCombineMode As Long) As Long
  17. 'Tipo de combinacion
  18. Const RGN_XOR = 3
  19. '----------------------------------------------------------------------------------------------------
  20. Public Sub MakeTransparent(TransForm As Form)
  21. Dim ErrorTest As Double
  22.     'en caso de que haya un error, se ignora
  23.     On Error Resume Next
  24.     
  25.     Dim Regn As Long
  26.     Dim TmpRegn As Long
  27.     Dim TmpControl As Control
  28.     Dim LinePoints(4) As POINTAPI
  29.     
  30.     'Puesto que las API trabajan en pixels, cambiamos el modo de escala a pixels
  31.     TransForm.ScaleMode = 3
  32.     
  33.     'Debe ejecutarse sobre un formulario son bordes.
  34.     If TransForm.BorderStyle <> 0 Then MsgBox "Cambia el borderstyle a 0!", vbCritical, "ACK!": End
  35.     
  36.     'Hace todo invisible
  37.     Regn = CreateRectRgn(0, 0, 0, 0)
  38.     
  39.     'Un bucle para controlar cada control en el formulario
  40.     For Each TmpControl In TransForm
  41.     
  42.         'Si el control es una linea...
  43.         If TypeOf TmpControl Is Line Then
  44.             'Comprueba la inclinacion
  45.             If Abs((TmpControl.Y1 - TmpControl.Y2) / (TmpControl.X1 - TmpControl.X2)) > 1 Then
  46.                 'Si es mas vertical que horizontal entonces..
  47.                 'Fija los puntos
  48.                 LinePoints(0).X = TmpControl.X1 - 1
  49.                 LinePoints(0).Y = TmpControl.Y1
  50.                 LinePoints(1).X = TmpControl.X2 - 1
  51.                 LinePoints(1).Y = TmpControl.Y2
  52.                 LinePoints(2).X = TmpControl.X2 + 1
  53.                 LinePoints(2).Y = TmpControl.Y2
  54.                 LinePoints(3).X = TmpControl.X1 + 1
  55.                 LinePoints(3).Y = TmpControl.Y1
  56.             Else
  57.                 'Si es mas horizontal que vertical, entonces...
  58.                 'Fija los puntos
  59.                 LinePoints(0).X = TmpControl.X1
  60.                 LinePoints(0).Y = TmpControl.Y1 - 1
  61.                 LinePoints(1).X = TmpControl.X2
  62.                 LinePoints(1).Y = TmpControl.Y2 - 1
  63.                 LinePoints(2).X = TmpControl.X2
  64.                 LinePoints(2).Y = TmpControl.Y2 + 1
  65.                 LinePoints(3).X = TmpControl.X1
  66.                 LinePoints(3).Y = TmpControl.Y1 + 1
  67.             End If
  68.             'Crea el nuevo poligono con los puntos
  69.             TmpRegn = CreatePolygonRgn(LinePoints(0), 4, 1)
  70.             
  71.         'Si el control es una figura...
  72.         ElseIf TypeOf TmpControl Is Shape Then
  73.             
  74.             'si es asi, comprobamos el tipo
  75.             If TmpControl.Shape = 0 Then
  76.             'Es un rectangulo
  77.                 TmpRegn = CreateRectRgn(TmpControl.Left, TmpControl.Top, TmpControl.Left + TmpControl.Width, TmpControl.Top + TmpControl.Height)
  78.             ElseIf TmpControl.Shape = 1 Then
  79.             'Es un cuadrado
  80.                 If TmpControl.Width < TmpControl.Height Then
  81.                     TmpRegn = CreateRectRgn(TmpControl.Left, TmpControl.Top + (TmpControl.Height - TmpControl.Width) / 2, TmpControl.Left + TmpControl.Width, TmpControl.Top + (TmpControl.Height - TmpControl.Width) / 2 + TmpControl.Width)
  82.                 Else
  83.                     TmpRegn = CreateRectRgn(TmpControl.Left + (TmpControl.Width - TmpControl.Height) / 2, TmpControl.Top, TmpControl.Left + (TmpControl.Width - TmpControl.Height) / 2 + TmpControl.Height, TmpControl.Top + TmpControl.Height)
  84.                 End If
  85.             ElseIf TmpControl.Shape = 2 Then
  86.             'Es un ovalo
  87.                 TmpRegn = CreateEllipticRgn(TmpControl.Left, TmpControl.Top, TmpControl.Left + TmpControl.Width + 0.5, TmpControl.Top + TmpControl.Height + 0.5)
  88.             ElseIf TmpControl.Shape = 3 Then
  89.             'Es un circulo
  90.                 If TmpControl.Width < TmpControl.Height Then
  91.                     TmpRegn = CreateEllipticRgn(TmpControl.Left, TmpControl.Top + (TmpControl.Height - TmpControl.Width) / 2, TmpControl.Left + TmpControl.Width + 0.5, TmpControl.Top + (TmpControl.Height - TmpControl.Width) / 2 + TmpControl.Width + 0.5)
  92.                 Else
  93.                     TmpRegn = CreateEllipticRgn(TmpControl.Left + (TmpControl.Width - TmpControl.Height) / 2, TmpControl.Top, TmpControl.Left + (TmpControl.Width - TmpControl.Height) / 2 + TmpControl.Height + 0.5, TmpControl.Top + TmpControl.Height + 0.5)
  94.                 End If
  95.             ElseIf TmpControl.Shape = 4 Then
  96.             'Es un rectangulo redondeado
  97.                 If TmpControl.Width > TmpControl.Height Then
  98.                     TmpRegn = CreateRoundRectRgn(TmpControl.Left, TmpControl.Top, TmpControl.Left + TmpControl.Width + 1, TmpControl.Top + TmpControl.Height + 1, TmpControl.Height / 4, TmpControl.Height / 4)
  99.                 Else
  100.                     TmpRegn = CreateRoundRectRgn(TmpControl.Left, TmpControl.Top, TmpControl.Left + TmpControl.Width + 1, TmpControl.Top + TmpControl.Height + 1, TmpControl.Width / 4, TmpControl.Width / 4)
  101.                 End If
  102.             ElseIf TmpControl.Shape = 5 Then
  103.        'Es un cuadrado redondeado
  104.                 If TmpControl.Width > TmpControl.Height Then
  105.                     TmpRegn = CreateRoundRectRgn(TmpControl.Left + (TmpControl.Width - TmpControl.Height) / 2, TmpControl.Top, TmpControl.Left + (TmpControl.Width - TmpControl.Height) / 2 + TmpControl.Height + 1, TmpControl.Top + TmpControl.Height + 1, TmpControl.Height / 4, TmpControl.Height / 4)
  106.                 Else
  107.                     TmpRegn = CreateRoundRectRgn(TmpControl.Left, TmpControl.Top + (TmpControl.Height - TmpControl.Width) / 2, TmpControl.Left + TmpControl.Width + 1, TmpControl.Top + (TmpControl.Height - TmpControl.Width) / 2 + TmpControl.Width + 1, TmpControl.Width / 4, TmpControl.Width / 4)
  108.                 End If
  109.             End If
  110.             
  111.             'Si el control es una figura con fondo transparente
  112.             If TmpControl.BackStyle = 0 Then
  113.                 
  114.                 'Combinamos la region en memoria y creamos una nueva
  115.                 CombineRgn Regn, Regn, TmpRegn, RGN_XOR
  116.                 
  117.                 If TmpControl.Shape = 0 Then
  118.                 'Rectangulo
  119.                     TmpRegn = CreateRectRgn(TmpControl.Left + 1, TmpControl.Top + 1, TmpControl.Left + TmpControl.Width - 1, TmpControl.Top + TmpControl.Height - 1)
  120.                 ElseIf TmpControl.Shape = 1 Then
  121.                 'Cuadrado
  122.                     If TmpControl.Width < TmpControl.Height Then
  123.                         TmpRegn = CreateRectRgn(TmpControl.Left + 1, TmpControl.Top + (TmpControl.Height - TmpControl.Width) / 2 + 1, TmpControl.Left + TmpControl.Width - 1, TmpControl.Top + (TmpControl.Height - TmpControl.Width) / 2 + TmpControl.Width - 1)
  124.                     Else
  125.                         TmpRegn = CreateRectRgn(TmpControl.Left + (TmpControl.Width - TmpControl.Height) / 2 + 1, TmpControl.Top + 1, TmpControl.Left + (TmpControl.Width - TmpControl.Height) / 2 + TmpControl.Height - 1, TmpControl.Top + TmpControl.Height - 1)
  126.                     End If
  127.                 ElseIf TmpControl.Shape = 2 Then
  128.                 'Ovalo
  129.                     TmpRegn = CreateEllipticRgn(TmpControl.Left + 1, TmpControl.Top + 1, TmpControl.Left + TmpControl.Width - 0.5, TmpControl.Top + TmpControl.Height - 0.5)
  130.                 ElseIf TmpControl.Shape = 3 Then
  131.                 'Circulo
  132.                     If TmpControl.Width < TmpControl.Height Then
  133.                         TmpRegn = CreateEllipticRgn(TmpControl.Left + 1, TmpControl.Top + (TmpControl.Height - TmpControl.Width) / 2 + 1, TmpControl.Left + TmpControl.Width - 0.5, TmpControl.Top + (TmpControl.Height - TmpControl.Width) / 2 + TmpControl.Width - 0.5)
  134.                     Else
  135.                         TmpRegn = CreateEllipticRgn(TmpControl.Left + (TmpControl.Width - TmpControl.Height) / 2 + 1, TmpControl.Top + 1, TmpControl.Left + (TmpControl.Width - TmpControl.Height) / 2 + TmpControl.Height - 0.5, TmpControl.Top + TmpControl.Height - 0.5)
  136.                     End If
  137.                 ElseIf TmpControl.Shape = 4 Then
  138.          'Rectangulo redondeado
  139.                     If TmpControl.Width > TmpControl.Height Then
  140.                         TmpRegn = CreateRoundRectRgn(TmpControl.Left + 1, TmpControl.Top + 1, TmpControl.Left + TmpControl.Width, TmpControl.Top + TmpControl.Height, TmpControl.Height / 4, TmpControl.Height / 4)
  141.                     Else
  142.                         TmpRegn = CreateRoundRectRgn(TmpControl.Left + 1, TmpControl.Top + 1, TmpControl.Left + TmpControl.Width, TmpControl.Top + TmpControl.Height, TmpControl.Width / 4, TmpControl.Width / 4)
  143.                     End If
  144.                 ElseIf TmpControl.Shape = 5 Then
  145.                 'Cuadrado redondeado
  146.                     If TmpControl.Width > TmpControl.Height Then
  147.                         TmpRegn = CreateRoundRectRgn(TmpControl.Left + (TmpControl.Width - TmpControl.Height) / 2 + 1, TmpControl.Top + 1, TmpControl.Left + (TmpControl.Width - TmpControl.Height) / 2 + TmpControl.Height, TmpControl.Top + TmpControl.Height, TmpControl.Height / 4, TmpControl.Height / 4)
  148.                     Else
  149.                         TmpRegn = CreateRoundRectRgn(TmpControl.Left + 1, TmpControl.Top + (TmpControl.Height - TmpControl.Width) / 2 + 1, TmpControl.Left + TmpControl.Width, TmpControl.Top + (TmpControl.Height - TmpControl.Width) / 2 + TmpControl.Width, TmpControl.Width / 4, TmpControl.Width / 4)
  150.                     End If
  151.                 End If
  152.             End If
  153.         Else
  154.                 'Crea una region rectangular con estos parametros
  155.                 TmpRegn = CreateRectRgn(TmpControl.Left, TmpControl.Top, TmpControl.Left + TmpControl.Width, TmpControl.Top + TmpControl.Height)
  156.             
  157.         End If
  158.             
  159.             'Comprueba que el control tiene ancho o conseguiremos extraños resultados
  160.             
  161.             ErrorTest = 0
  162.             ErrorTest = TmpControl.Width
  163.             If ErrorTest <> 0 Or TypeOf TmpControl Is Line Then
  164.                 'Combina las regiones
  165.                 CombineRgn Regn, Regn, TmpRegn, RGN_XOR
  166.             End If
  167.         
  168.     Next TmpControl
  169.     
  170.     'Crea las regiones
  171.     SetWindowRgn TransForm.hwnd, Regn, True
  172.     
  173.  
  174. End Sub
  175.  

 Bueno todo corresponde a las declaraciones del form, y deben tener en cuenta que el "Option Explicit" va primero si lo queremos incluir en otras declaraciones.
Ahora, para hacer el formulario transparente, basta que en el form_load coloquemos: --> MakeTransparent Me

 Bueno con eso basta tendremos un buen efecto en nuestros formularios de suspencion de los objetos y textos.

Saludos y espero que a alguien le sea de utilidad  ;)

L3andro.

Páginas: [1]